Получение кода выхода из команды 'ftp' в оболочке linux - PullRequest
10 голосов
/ 04 февраля 2011

Мне нужно получить код состояния выхода из программы командной строки. Не беспокойтесь, я использовал $ ?. Но для ftp, даже если он не подключается, он открывает оболочку ftp, поэтому я не могу понять, что подключение не состоялось.

Попробуйте этот код для понимания:

#!/bin/sh

ftp 1234567
OUT=$?
if [ $OUT -eq 0 ];then
   echo "ftp OK"
else
   echo "ftp Error: "$OUT
fi

exit 0

Любая помощь? Спасибо Филиппо

Ответы [ 6 ]

19 голосов
/ 04 февраля 2011

Вы должны искать сообщение об успешном выполнении команды ftp, а не искать статус.Это «226 передача завершена».Вы можете подтвердить это с помощью руководства ftp в вашей системе.

200 PORT command successful.
150 Opening ASCII mode data connection for filename.
226 Transfer complete.
189 bytes sent in 0.145 seconds (0.8078 Kbytes/s)

Вот пример сценария.

FTPLOG=/temp/ftplogfile
ftp -inv <<! > $FTPLOG
open server
user ftp pwd
put filename
close
quit
!

FTP_SUCCESS_MSG="226 Transfer complete"
if fgrep "$FTP_SUCCESS_MSG" $FTPLOG ;then
   echo "ftp OK"
else
   echo "ftp Error: "$OUT
fi
exit 0
5 голосов
/ 04 февраля 2011

Если вам нужно что-то скачать и посмотреть, удалась ли загрузка, почему бы вам не использовать wget ?Он поддерживает протокол FTP.

Он сообщит о состоянии загрузки с несколькими кодами возврата (цитата из справочной страницы):

EXIT STATUS
   Wget may return one of several error codes if it encounters problems.
   0   No problems occurred.
   1   Generic error code.
   2   Parse error---for instance, when parsing command-line options, the .wgetrc or .netrc...
   3   File I/O error.
   4   Network failure.
   5   SSL verification failure.
   6   Username/password authentication failure.
   7   Protocol errors.
   8   Server issued an error response.
2 голосов
/ 31 мая 2012

Попробуйте следующие сценарии.

Для копирования:

#!/bin/bash
# cftp.sh
# set -x

FTPSERVER="$1"
FTPPORT="$2"
REMOTEDIR="$3"

[[ "$REMOTEDIR" ]] || { echo -e "Usage: $0 <ftpserver> <ftpport> <remotedir> [file1] [file2] ..." > /dev/stderr ; exit 1 ; }

L=$((BASH_ARGC-3))

LOCALFILES=("${BASH_ARGV[@]:0:$L}")

RETCODE=0

for LOCALFILE in "${LOCALFILES[@]}"
do
  THISRETCODE=0
  [[ -f "$LOCALFILE" ]] || THISRETCODE=1

  LOCALDIR="$(dirname "$LOCALFILE")"
  LOCALFILENAME="$(basename "$LOCALFILE")"

  [[ $THISRETCODE = 0 ]] &&
  /usr/bin/ftp -iv "$FTPSERVER" << EOF | grep -q '226 Transfer complete' || THISRETCODE=1
    lcd $LOCALDIR
    cd $REMOTEDIR
    put $LOCALFILENAME
EOF

  RETCODE=$((RETCODE+THISRETCODE))
done

exit $RETCODE

Для перемещения:

#!/bin/bash
# mftp.sh
# set -x

FTPSERVER="$1"
FTPPORT="$2"
REMOTEDIR="$3"

[[ "$REMOTEDIR" ]] || { echo -e "Usage: $0 <ftpserver> <ftpport> <remotedir> [file1] [file2] ..." > /dev/stderr ; exit 1 ; }

L=$((BASH_ARGC-3))

LOCALFILES=("${BASH_ARGV[@]:0:$L}")

RETCODE=0

for LOCALFILE in "${LOCALFILES[@]}"
do
  THISRETCODE=0
  [[ -f "$LOCALFILE" ]] || THISRETCODE=1

  LOCALDIR="$(dirname "$LOCALFILE")"
  LOCALFILENAME="$(basename "$LOCALFILE")"

  [[ $THISRETCODE = 0 ]] &&
  /usr/bin/ftp -iv "$FTPSERVER" << EOF | grep -q '226 Transfer complete' || THISRETCODE=1
    lcd $LOCALDIR
    cd $REMOTEDIR
    put $LOCALFILENAME
EOF

  [[ $THISRETCODE = 0 ]] &&
  /bin/rm -f "$LOCALFILE" || THISRETCODE=1

  RETCODE=$((RETCODE+THISRETCODE))
done

exit $RETCODE

Вот несколько тестов:

Для копирования.

$ ./cftp.sh ; echo return code: $?
Usage: ./cftp.sh <ftpserver> <ftpport> <remotedir> [file1] [file2] ...
return code: 1
$ ./cftp.sh ftpserver 21 /mnt/disk4/d0/test ; echo return code: $?
return code: 0
$ ./cftp.sh ftpserver 21 /mnt/disk4/d0/test cftp.sh mftp.sh ; echo return code: $?
return code: 0
$ ./cftp.sh ftpserver 21 /mnt/disk4/d0/test *ftp.sh ; echo return code: $?
return code: 0
$ ./cftp.sh ftpserver 21 /mnt/disk4/d0/test cftp.s ; echo return code: $?
return code: 1
$ ./cftp.sh ftpserver 21 /mnt/disk4/d0/test cftp.s mftp.s ; echo return code: $?
return code: 2
$ ./cftp.sh ftpserver 21 /mnt/disk4/d0/tes cftp.sh ; echo return code: $?
return code: 1

Для перемещения.

$ ./mftp.sh ftpserver 21 /mnt/disk4/d0/test cftp.sh ; echo return code: $?
/bin/rm: cannot remove `cftp.sh': Permission denied
return code: 1
$ echo foo > /tmp/bar
$ ./mftp.sh ftpserver 21 /mnt/disk4/d0/test /tmp/bar ; echo return code: $?
return code: 0
$ ls -lha /tmp/bar
ls: cannot access /tmp/bar: No such file or directory

Обновление: не забудьте прочитать man 5 netrc

1 голос
/ 04 февраля 2011

некоторые сценарии выполняют -

ftp -n $HOST > /tmp/ftp.worked 2> /tmp/ftp.failed <<END_SCRIPT
blah blah
END_SCRIPT

EXITSTATUS=$?

if [ $EXITSTATUS != "0" ]
then
    # handle the error...
fi 

За исключением того, что вышеупомянутое не всегда работает - большинство FTP-клиентов всегда выходят со статусом 0. Это приводит к ужасным «ложным негативам»:передача файла не удалась, но сценарий не обнаружил проблему.

Один из способов проверить, что передача файла произошла - передать ее обратно:

#!/bin/sh

ftp -n << END_SCRIPT
open $1
user $2 $3
put $4
get $4 retrieval.$$
bye
END_SCRIPT

if [ -f retrieval.$$ ]
then
    echo "FTP of $4 to $1 worked"
    rm -f retrieval.$$
else
    echo "FTP of $4 did not work"
fi
0 голосов
/ 15 января 2015

Другой способ - проверить, есть ли файл на вашем сервере после передачи!

Что-то вроде ...

if ![ -s "$INPUT_DIR/HOP_PSA_Transactions_$BATCH_ID.csv" ]
then
    ## No Transactions file
    FAIL_TIME=`date +"%d-%m-%Y %H:%M"`
	echo "ERROR: File HOP_PSA_Transactions_$BATCH_ID.csv not found @ $FAIL_TIME" >>$LOGFILE_DIR$LOGFILE_NAME
	exit $ERR_NO_TRANS_FILE    
fi

Если его нет, значит, он не был успешно передан!

0 голосов
/ 04 февраля 2011

В последний раз, когда мне нужно было использовать ftp в скрипте, я был настолько разочарован этим, что наконец-то нашел лицензированный BSD исходный код клиента ftp и просто изменил его, чтобы придать ему необходимое мне поведение, и использовал его вместоверсия, поставляемая с ОС.

Ужасно, но глубина вмятин на уровне головы в стенке куба начинала становиться смешной

...