0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【シェル】expectを用いてsshで実行したコマンドの終了ステータスを取得する方法

Last updated at Posted at 2025-01-21

想定されるケース

・sshしてコマンドを実行するところまで自動化したい
・公開鍵認証ではなく、パスワード認証になっている(非推奨)
・パスワード認証も自動で突破したい
・expectを採用するしかない
・sshで実行したコマンドの戻り値を、シェル内で使用したい

こんな限られた場面・環境でシェルの作成を余儀なくされた...。
そんなあなたのために書き残します。(当然筆者も含まれます)

結論

以下のようなコードを書けば実現できます。

#!/bin/bash

expect -c "
set timeout 10
spawn -noecho ssh ${USER}@${REMOTE_HOST} \"${COMMAND}\"
expect \"assword\"
send \"${PASSWORD}\"
interact
exit [lindex [wait] 3]
"
echo $? # ${COMMAND}の終了ステータスが出力される

ポイント

以下の記述が大事なところです。

exit [lindex [wait] 3]

[ ]:コマンド置換。$( )と同様コマンドの実行結果に置換される。
exit:expectコマンドを終了するの意です。
lindex:関数。lindex [配列] [index]と引数を指定して記述すると、indexに対応する配列の要素を取得できる。
wait:少しややこしいので、manコマンドの記述を見てみましょう。

spawnされたプロセス(あるいは、名前つきのプロセスがなければ現在のプロセス) が終了するのを待つ。
wait は、通常4つの整数のリストを帰す。
最初の整数は、終了を待ち構えているプロセスの pid である。
2つめの整数は、関連するspawn idである。
3 つめの整数は、オペレーティングシステムエラーがあれば -1、 そうでなければ、0である。 
3 つめの整数が 0 であれば、4 つめの整数はspawnされたプロセスからのリターン コードである。
3 つめの整数が -1 であれば、4 つめの整数はオペレーティングシステム によって設定された errno の値である。グローバル変数 errorCode も設定される。

結局、ややこしいわ

というわけで、要点だけまとめてみました。

spawnされたプロセスの終了後に通常4つの整数のリストを帰す
4つめの整数はspawnされたプロセスからのリターンコードである

これで、少しは理解が進んだのではないでしょうか。

コマンドをもう一度眺める

ここでexit [lindex [wait] 3]をもう一度見てみましょう。
以下のような流れで変換されていきます。

exit [lindex [wait] 3]

↓  waitがコマンド置換されて配列に置き換わる。4番目に終了ステータスが入っている。

exit [lindex (pid spawnid OSerr exitcode) 3]

↓  lindex関数もコマンド置換され、4番目の要素(index=3)である終了ステータスを取得し置き換わる。

exit "exitcode"

最後に

最初に述べたように、想定されるケースはかなり狭いです。
sshでは鍵認証を使用すべきで、パスワード認証を自動化するためにexpectを用いること自体非推奨です。
(そもそもパスワードの扱いに困ります。平文でどこかに記載するなんてのは厳禁です。)

「構成・環境の変更なんて今更できない!制約がある中でなんとかしないといけないんだ!」という方のある種"特効薬"になれば幸いです。

ここまで読んでいただきありがとうございました。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?