web-dev-qa-db-ja.com

sshがcron bashスクリプトから実行するとリモートコマンドの実行に失敗する-CLIから機能する

Cronから実行されるbashで記述されたスクリプトがあります。最初に行うことの1つは、リモートホストに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でデバッグフラグを使用し始めました。コマンドラインから1回実行し、次にcronから実行して、出力を比較しました。以下は、diffのハイライトです。

-側は失敗した試行であり、+側は成功した試行であり、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.

これらの余分なファイル記述子がcronから実行されたときにdebug2で言及される理由を説明することはできませんが、関連しているようです(以下の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

どんなアイデアでもとても高く評価されています。

5
Kyle Smith

SSH接続オプションに-t -tを追加してみてください。この意志;疑似端末を強制的に割り当てます。

複数の-tオプションは、sshにローカルttyがない場合でも、ttyの割り当てを強制します。

8
meanasspenguin

スクリプトをさらにデバッグする必要があります。試す2つのこと:

出力リダイレクトを介さずに直接ファイル出力を行うようにRwriteします。つまり、スクリプトで次のようにします。

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

Cron内でbash-xを使用してスクリプトを実行し、結果を保存します。スクリプトの最初の行を#!/bin/bash -xに変更して、次のように試してください

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

これにより、スクリプトの実行内容を正確に絞り込むことができます。この場合、cronでの出力のリダイレクトが正しく機能していないと思われます。

また、ばかげた質問:rootが/root/path/to/last_run_outputに書き込むことができることを確認しましたか?スクリプトがcronで実行されているときにnoclobberが設定されていないことを確認しましたか?

編集:OPからのコメントに基づいたさらなるトラブルシューティングのアイデア。

したがって、上記のアイデアはどれも機能していないようです。フィーリストをリモートマシン上のファイルに保存して、元に戻すのはどうですか?これにより、奇妙な引用や入力リダイレクトの問題が解消されます。

1
Phil Hollenback