- Editar: resuelto. Ver respuesta.

Antecedentes: estoy escribiendo un shell que realizará algunas acciones adicionales requeridas en nuestro sistema cuando alguien cambie el tamaño de una base de datos. El shell está escrito en ksh (requisito), el sistema operativo es Solaris 5.10. El problema es con una de las comprobaciones, que verifica que hay suficiente espacio libre en el sistema operativo subyacente.

Problema: La verificación lee la línea df -k para root, que es lo que verifico en este paso, y la imprime en un archivo. Luego "leo" los contenidos en variables que uso en los cálculos. Desafortunadamente, cuando intento ejecutar una operación aritmética en una de las variables, aparece un error que indica que es nulo. Y una línea de salida de depuración que coloqué después de esa línea verifica que es nula ... Perdió su valor ...

He probado todos los métodos para hacer esto que pude encontrar en línea, funcionan cuando lo ejecuto manualmente, pero no dentro del archivo de shell. (* El archivo tiene #! / Usr / bin / ksh)

Código:

df -k | grep "rpool/ROOT" > dftest.out  
RPOOL_NAME=""; declare -i TOTAL_SIZE=0; USED_SPACE=0; AVAILABLE_SPACE=0; AVAILABLE_PERCENT=0; RSIGN=""  
read RPOOL_NAME TOTAL_SIZE USED_SPACE AVAILABLE_SPACE AVAILABLE_PERCENT RSIGN < dftest.out  
\rm dftest.out  
echo $RPOOL_NAME $TOTAL_SIZE $USED_SPACE $AVAILABLE_SPACE $AVAILABLE_PERCENT $RSIGN  
((TOTAL_SIZE=$TOTAL_SIZE/1024))  

Este es el resultado:
DBResize.sh [11]: TOTAL_SIZE = / 1024: error de sintaxis

Estoy tirando de los pelos en este punto, cualquier ayuda sería apreciada.

0
ziv 13 sep. 2018 a las 13:19

3 respuestas

La mejor respuesta

El código que publicó no puede producir la salida que publicó. Obviamente, el error se señala en la línea 11, pero publicó menos de 11 líneas de código. Las líneas anteriores pueden ser importantes. Siempre solicite código completo cuando solicite ayuda.

Más concretamente, el comando declare no existe en ksh, es una cosa bash. Puede lograr el mismo resultado con typeset (declare es un bash equivalente a typeset, pero no todas las opciones son iguales). O está ejecutando este script con bash, o hay otro mensaje de error sobre declare, o ha definido algunos comandos adicionales que incluyen declare que pueden cambiar el comportamiento de este código.

Sin embargo, nada de esto debería tener un impacto en el problema particular sobre el que está publicando. Las variables creadas por read permanecen asignadas hasta el final de la subshell, es decir, hasta que el código llegue a ), el final de una tubería (el lado izquierdo de la tubería solo en ksh), etc.

Sobre el uso de declare o typeset, tenga en cuenta que solo está declarando TOTAL_SIZE como un número entero. Para las otras variables, solo está asignando un valor que consiste exclusivamente en dígitos. No importa el código que publicaste, pero probablemente no sea lo que querías decir.

Una cosa que puede estar sucediendo es que grep no coincide con nada y, por lo tanto, read lee una línea vacía. Debe verificar si hay errores. Use set -e en los scripts para salir en el primer error. (Hay casos en los que set -e no detecta errores, pero es un buen comienzo).

Otra cosa que puede estar sucediendo es que df está dividiendo su salida en varias líneas porque la primera columna que contiene el nombre del sistema de archivos es demasiado grande. Para evitar esta división, pase la opción -P.

El uso de un archivo temporal es frágil: el código puede ejecutarse en un directorio de solo lectura, otro proceso puede querer acceder al mismo archivo al mismo tiempo ... Aquí un archivo temporal es inútil. Simplemente canalice directamente en read. En ksh (a diferencia de la mayoría de las otras variantes de sh, incluido bash), el lado derecho de una tubería se ejecuta en el shell principal, por lo que las asignaciones a las variables en el lado derecho de una tubería permanecen disponibles en los siguientes comandos.

No importa en este script en particular, pero puede usar una variable sin $ en una expresión aritmética. El uso de $ sustituye una cadena que puede tener resultados confusos, p. a='1+2'; $((a*3)) se expande a 7. Al no usar $ se usa el valor numérico (en ksh, a='1+2'; $((a*3)) se expande a 9; en algunas implementaciones de sh se obtiene un error porque el valor de a no es numérico).

#!/usr/bin/ksh
set -e
typeset -i TOTAL_SIZE=0 USED_SPACE=0 AVAILABLE_SPACE=0 AVAILABLE_PERCENT=0
df -Pk | grep "rpool/ROOT" | read RPOOL_NAME TOTAL_SIZE USED_SPACE AVAILABLE_SPACE AVAILABLE_PERCENT RSIGN  
echo $RPOOL_NAME $TOTAL_SIZE $USED_SPACE $AVAILABLE_SPACE $AVAILABLE_PERCENT $RSIGN  
((TOTAL_SIZE=TOTAL_SIZE/1024))
0
Gilles 'SO- stop being evil' 15 sep. 2018 a las 07:06

Extraño ... cuando me deshago de su línea "declarar", su código original parece funcionar perfectamente bien (al menos con ksh en Linux)

El código :

#!/bin/ksh

df -k | grep "/home" > dftest.out
read RPOOL_NAME TOTAL_SIZE USED_SPACE AVAILABLE_SPACE AVAILABLE_PERCENT RSIGN < dftest.out
\rm dftest.out

echo $RPOOL_NAME $TOTAL_SIZE $USED_SPACE $AVAILABLE_SPACE $AVAILABLE_PERCENT $RSIGN
((TOTAL_SIZE=$TOTAL_SIZE/1024))
print $TOTAL_SIZE

El resultado :

32962416 5732492 25552588 19% /home
5598

¿Cuáles son los valores que devuelve un simple df -k? Las variables parecen durar.

0
Andre Gelinas 15 sep. 2018 a las 04:22

Para aquellos interesados, he descubierto que no es posible usar "leer" como lo estaba usando.
Los valores variables asignados por "leer" simplemente "no duran".
Para remediar esto, he aplicado la solución menos que ideal de usar el formato estándar "mientras se lee", y dentro del bucle, hacer eco de las variables seleccionadas en un archivo variable.
Una vez que dicho archivo fue creado, simplemente lo "cargué".

(pseudocódigo :)

LOOP START
echo "VAR_A="$VAR_A"; VAR_B="$VAR_B";" > somefile.out
LOOP END
. somefile.out
-1
ziv 13 sep. 2018 a las 21:13