あるサーバからリモートにあるサーバにログインし、コマンドを実行したい、ということが時々あるかと思います。
単純なコマンドの場合はssh ユーザ名@ログイン先 実行コマンド
として直接書けばよいのですが、複数の処理を行おうとした場合、この方法では可読性が犠牲になります。
そのため、対策として例えば次のように書くと多少長くなっても読みやすいです。
下記はリモートのhomeディレクトリにあるファイル及びディレクトリの数を数えて、1以上なら"not empty!"と出力するシェルスクリプトです。
sample.sh
#!/bin/bash
cat << EOF > "cmd.txt"
if [ `ls -1U "/home/" | wc -l` -gt "0" ]; then
echo "not empty!"
fi
EOF
cmd=`cat "cmd.txt"`
rm "cmd.txt"
ssh root@127.0.0.1 "${cmd}"
ところで、上記の通りに実行すると、想定通りに動きません。if文の中のls
やwc
がローカルで実行されてしまい、${cmd}
に格納される値は次のようになってしまいます。
if [ 1 -gt "0" ]; then
echo "not empty!"
fi
リモートで``に囲まれたコマンドを実行するにはどうしたらよいでしょうか。
sample_fixed.sh
#!/bin/bash
echo '
if [ `ls -1U "/home/" | wc -l` -gt "0" ]; then
echo "not empty!"
fi
' > script.sh
ssh root@127.0.0.1 'bash -s' < script.sh
このようにすれば可能です。
bash -s
によって、標準入力から実行するコマンドを流し込めます。
尚、上記の例で変数を使用する場合は次のようにします。
sample_fixed_improved.sh
#!/bin/bash
echo '
if [ `ls -1U "/home/" | wc -l` -gt "0" ]; then
echo "'${HOME}' is not empty!"
fi
' > script.sh
ssh root@127.0.0.1 'bash -s' < script.sh
${HOME}
変数の前後にシングルクオート('
)を加えることにより、
変数の中身を出力するようにしています。
参考
- Execute inside of back-quote command on ssh 自力で解決ができず、StackOverflowにて質問したところ、回答を得られました。回答内容に変数利用のための記述を追加してこの記事を書いています。