Назад | Перейти на главную страницу

ssh не может выполнить удаленную команду при запуске из cron bash скрипта - работает из CLI

У меня есть сценарий, написанный на bash, который запускается из cron. Одно из первых, что он делает, - это SSH к удаленному хосту и получение списка файлов в каталоге. При запуске из командной строки все работает нормально, но не из cron.

Первоначально раздел скрипта выглядел так:

FILES=$($SSH_BINARY -i $SSH_KEY $SSH_USER@$REMOTE_HOST "ls $REMOTE_DIRECTORY")
echo "Got files = $FILES"

Я добавил эхо-запрос над этой строкой (показано ниже), чтобы доказать, что это не проблема пути или переменной:

echo "$SSH_BINARY -i $SSH_KEY $SSH_USER@$REMOTE_HOST \"ls $REMOTE_DIRECTORY\""

Если я возьму полученную строку вывода и запустил ее от имени того же пользователя cron (root), она будет работать без проблем.

Думая, что это может иметь какое-то отношение к присвоению переменной, я изменил строку FILES = для чтения (таким образом, поместив вывод прямо в мой файл last_run_output):

$SSH_BINARY -vv -i $SSH_KEY $SSH_USER@$REMOTE_HOST "ls $REMOTE_DIRECTORY"

Запись cron выглядит так:

34 * * * * /root/path/to/my/script/get_logs.sh > /root/path/to/last_run_output 2>&1

Итак, если оставить в стороне проблемы с PATH, назначением переменных и разрешениями, я начал использовать флаги отладки в ssh. Я запустил один раз из командной строки, затем из cron и сравнил результаты. Вот несколько основных моментов из разницы:

Сторона - - неудачная попытка, сторона + - успешная попытка, запускаемая вне cron.

@@ -87,9 +77,7 @@
 debug1: Remote: X11 forwarding disabled.
 debug1: Remote: Forced command: /home/sshacs/acssshsink netstorageuser
 debug1: Authentication succeeded (publickey).
-debug2: fd 4 setting O_NONBLOCK
 debug2: fd 5 setting O_NONBLOCK
-debug2: fd 6 setting O_NONBLOCK
 debug1: channel 0: new [client-session]
 debug2: channel 0: send open
 debug1: Entering interactive session.

Я не могу объяснить, почему эти дополнительные файловые дескрипторы упоминаются в debug2 при запуске из cron, но, похоже, они связаны (обратите внимание на строку read <= 0 rfd 4 len 0 ниже):

@@ -100,20 +88,672 @@
 debug2: callback done
 debug2: channel 0: open confirm rwindow 0 rmax 32768
 debug2: channel 0: rcvd adjust 131072
-debug2: channel 0: read<=0 rfd 4 len 0
-debug2: channel 0: read failed
-debug2: channel 0: close_read
-debug2: channel 0: input open -> drain
-debug2: channel 0: ibuf empty
-debug2: channel 0: send eof
-debug2: channel 0: input drain -> closed
+  [[ Very large output of the ls command ]]
+debug1: client_input_channel_req: channel 0 rtype exit-status reply 0
 debug2: channel 0: rcvd eof
 debug2: channel 0: output open -> drain
 debug2: channel 0: obuf empty
 debug2: channel 0: close_write
 debug2: channel 0: output drain -> closed
-debug1: client_input_channel_req: channel 0 rtype exit-status reply 0
 debug2: channel 0: rcvd close
+debug2: channel 0: close_read
+debug2: channel 0: input open -> closed
 debug2: channel 0: almost dead
 debug2: channel 0: gc: notify user
 debug2: channel 0: gc: user detached

Любые идеи сильно оценен.

Попробуйте добавить -t -t к параметрам подключения SSH. Это будет; принудительно выделить псевдотерминал.

Множественный -t опции принудительно выделяют tty, даже если ssh не имеет местного tty.

Вам следует продолжить отладку вашего скрипта. Две вещи, которые стоит попробовать:

Перепишите его, чтобы выводить файл напрямую, а не через перенаправление вывода. То есть в скрипте сделать так:

$SSH_BINARY -i $SSH_KEY $SSH_USER@$REMOTE_HOST "ls $REMOTE_DIRECTORY" > savefile

Запустите ваш скрипт с bash -x внутри cron и сохраните результат. Измените первую строку скрипта на #!/bin/bash -x и попробуйте что-нибудь вроде

34 * * * * /root/path/to/my/script/get_logs.sh > script_debug 2>&1

это должно помочь вам сузить круг задач, которые выполняет ваш сценарий. Я подозреваю, что перенаправление вывода в cron в этом случае работает некорректно.

Кроме того, глупый вопрос: вы проверили, что root может писать в /root/path/to/last_run_output? Вы подтвердили, что у вас нет noclobber установить как-нибудь при запуске скрипта в cron?

РЕДАКТИРОВАТЬ: дальнейшие идеи по устранению неполадок на основе комментариев OP.

Так что ни одна из вышеперечисленных идей, похоже, не работает. Как насчет сохранения списка файлов в файле на удаленной машине и отправки его обратно? Это устранило бы любые странные проблемы с цитированием или перенаправлением ввода.