Pregunta

Actualmente estoy creando un trabajo nocturno que llama a un script Unix que a su vez crea y transfiere un archivo usando ftp . Me gustaría verificar todos los códigos de retorno posibles. La página del manual para ftp no enumera los códigos de retorno. ¿Alguien sabe dónde encontrar una lista? ¿Alguien con experiencia en esto? Tenemos otros scripts que buscan ciertas cadenas de retorno en el registro, y envían un correo electrónico cuando se produce un error. Sin embargo, a menudo pierden códigos imprevistos. Luego pongo el motivo en el registro y el correo electrónico.

¿Fue útil?

Solución

El comando ftp no devuelve nada más que cero en la mayoría de las implementaciones que he encontrado.

Es mucho mejor procesar los códigos de tres dígitos en el registro, y si está enviando un archivo binario, puede verificar que los bytes enviados fueron correctos.

Los códigos de tres dígitos se denominan 'códigos de serie' y se puede encontrar una lista aquí

Otros consejos

Escribí un script para transferir solo un archivo a la vez y en ese script use grep para verificar el mensaje 226 Transfer complete . Si lo encuentra, grep devuelve 0.

ftp -niv < "$2"_ftp.tmp | grep "^226 "

Instale el paquete ncftp . Viene con ncftpget y ncftpput que intentará cargar / descargar un solo archivo y volver con un código de error descriptivo si hay un problema. Consulte el & # 8220; Diagnóstico & # 8221; sección de la página del manual .

Creo que es más fácil ejecutar el ftp y verificar el código de salida de ftp si algo sale mal.

Hice esto como el siguiente ejemplo:

# ...
ftp -i -n $HOST 2>&1 1> $FTPLOG << EOF
quote USER $USER
quote PASS $PASSWD
cd $RFOLDER
binary
put $FOLDER/$FILE.sql.Z $FILE.sql.Z
bye
EOF

# Check the ftp util exit code (0 is ok, every else means an error occurred!)
EXITFTP=$?
if test $EXITFTP -ne 0; then echo "$D ERROR FTP" >> $LOG; exit 3; fi
if (grep "^Not connected." $FTPLOG); then echo "$D ERROR FTP CONNECT" >> $LOG; fi 
if (grep "No such file" $FTPLOG); then echo "$D ERROR FTP NO SUCH FILE" >> $LOG; fi 
if (grep "access denied" $FTPLOG ); then echo "$D ERROR FTP ACCESS DENIED" >> $LOG; fi
if (grep "^Please login" $FTPLOG ); then echo "$D ERROR FTP LOGIN" >> $LOG; fi

Editar: para detectar errores, grep la salida del comando ftp. Pero realmente no es la mejor solución.

No sé qué tan familiar eres con un lenguaje de script como Perl, Python o Ruby. Todos tienen un módulo FTP que puedes usar. Esto le permite verificar si hay errores después de cada comando. Aquí hay un ejemplo en Perl:

#!/usr/bin/perl -w
use Net::FTP;
$ftp = Net::FTP->new("example.net") or die "Cannot connect to example.net: $@";
$ftp->login("username", "password") or die "Cannot login ", $ftp->message;
$ftp->cwd("/pub") or die "Cannot change working directory ", $ftp->message;
$ftp->binary;
$ftp->put("foo.bar") or die "Failed to upload ", $ftp->message;
$ftp->quit;

Para que esta lógica funcione, el usuario debe redirigir STDERR también desde el comando ftp como se muestra a continuación

ftp -i -n $HOST >$FTPLOG 2>&1 << EOF

El siguiente comando siempre asignará 0 (éxito) porque el comando ftp no devolverá el éxito o el fracaso. Entonces el usuario no debería depender de ello

EXITFTP=$?

respuesta tonta lo sé, pero ¿qué hay de obtener las fuentes de ftp y ver por ti mismo

Me gusta la solución de Anurag, para el problema de transferencia de bytes he extendido el comando con grep -v " bytes "

es decir

grep " ^ 530 " ftp_out2.txt | grep -v " byte "

-en lugar de 530 puede usar todos los códigos de error como lo hizo Anurag.

Dijiste que querías enviar el archivo por FTP allí, pero no dijiste si el cliente regular BSD FTP era o no la única forma en que lo querías conseguir allí. BSD FTP no le proporciona un código de retorno para las condiciones de error que requieren todo ese análisis, pero hay una serie completa de otros programas de Unix que se pueden usar para transferir archivos por FTP si usted o su administrador los instalan. Le daré algunos ejemplos de formas de transferir un archivo por FTP sin dejar de detectar todas las condiciones de error con pequeñas cantidades de código.

FTPUSER es su nombre de inicio de sesión de usuario ftp

FTPPASS es su contraseña ftp

ARCHIVO es el archivo local que desea cargar sin ninguna información de ruta (por ejemplo, archivo1.txt, no /whatever/file1.txt o lo que sea / file1.txt

FTPHOST es la máquina remota a la que desea enviar FTP

REMOTEDIR es un CAMINO ABSOLUTO a la ubicación en la máquina remota a la que desea cargar

Aquí están los ejemplos:

curl --user $ FTPUSER: $ FTPPASS -T $ FILE ftp: // $ FTPHOST /% 2f $ REMOTEDIR

ftp-upload --host $ FTPHOST --user $ FTPUSER --password $ FTPPASS --as $ REMOTEDIR / $ FILE $ FILE

tnftp -u ftp: // $ FTPUSER: $ FTPPASS @ $ FTPHOST /% 2f $ REMOTEDIR / $ FILE $ FILE

wput $ FILE ftp: // $ FTPUSER: $ FTPPASS @ $ FTPHOST /% 2f $ REMOTEDIR / $ FILE

Todos estos programas devolverán un código de salida distinto de cero si algo sale mal, junto con el texto que indica qué falló. Puede probar esto y luego hacer lo que quiera con la salida, registrarlo, enviarlo por correo electrónico, etc. como desee.

Sin embargo, tenga en cuenta lo siguiente:

  1. "% 2f " se usa en las URL para indicar que la siguiente ruta es una ruta absoluta en la máquina remota. Sin embargo, si su servidor FTP lo arruina, no podrá evitarlo.

  2. para los comandos anteriores que usan una URL real ( ftp: // etc ) al servidor con el usuario y la contraseña incrustada en él, el nombre de usuario y la contraseña DEBEN estar codificados en URL si contienen caracteres especiales.

  3. En algunos casos, puede ser flexible con el directorio remoto como absoluto y el archivo local como el nombre de archivo simple una vez que esté familiarizado con la sintaxis de cada programa. Es posible que solo tenga que agregar una variable de entorno de directorio local o simplemente codificar todo.

  4. SI realmente, DEBE usar absolutamente un cliente FTP normal, una forma de probar la falla es, dentro de su script, incluyendo primero un comando que PONE el archivo, seguido de otro que haga un GET del mismo archivo que lo devuelve con un nombre diferente. Después de que FTP salga, simplemente pruebe la existencia del archivo descargado en su script de shell, o incluso haga una suma de comprobación con el original para asegurarse de que se transfirió correctamente. Sí, eso apesta, pero en mi opinión, es mejor tener un código que sea fácil de leer que analizar mucho cada posible error. BSD FTP no es tan bueno.

Esto es con lo que finalmente fui. Gracias por toda la ayuda. Todas las respuestas ayudan a guiarme en la dirección correcta. Puede ser un poco exagerado, verificando tanto el resultado como el registro, pero debería cubrir todas las bases.

echo "open ftp_ip
pwd
binary    
lcd /out
cd /in
mput datafile.csv
quit"|ftp -iv > ftpreturn.log

ftpresult=$?

bytesindatafile=`wc -c datafile.csv | cut -d " " -f 1`    
bytestransferred=`grep -e '^[0-9]* bytes sent' ftpreturn.log | cut -d " " -f 1`    
ftptransfercomplete=`grep -e '226 ' ftpreturn.log | cut -d " " -f 1`

echo "-- FTP result code: $ftpresult" >> ftpreturn.log
echo "-- bytes in datafile: $bytesindatafile bytes" >> ftpreturn.log
echo "-- bytes transferred: $bytestransferred bytes sent" >> ftpreturn.log

if [ "$ftpresult" != "0" ] || [ "$bytestransferred" != "$bytesindatafile" ] || ["$ftptransfercomplete" != "226" ]    
then    
  echo "-- *abend* FTP Error occurred" >> ftpreturn.log    
  mailx -s 'FTP error' `cat email.lst` < ftpreturn.log
else    
  echo "-- file sent via ftp successfully" >> ftpreturn.log    
fi

¿Por qué no simplemente almacenar toda la salida del comando en un archivo de registro, luego verificar el código de retorno del comando y, si no es 0, enviar el archivo de registro en el correo electrónico?

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top