私のスクリプトが最初の行の後にループを出る理由を理解できません。 deleteUser関数内で別のスクリプトを呼び出しているため、動作が中断されるようです。
以下は私のスクリプトから抜粋したものです。
[...]
function deleteUser
{
nfsserver="/local/scripts/find_home_in_nfs.sh ${1}"
ssh -n $nfsserver "rm -rf /home/${1}"
ssh ldap "sudo deleteUser ${1}"
userHome ${1}
}
cat myFile | while read line
do
username=`echo ${line} | awk -F" " '{print $1}'`
action=`echo ${line} | awk -F" " '{print $2}'`
if [ "${action}" == "d" ]; then
deleteUser ${username}
elif [ "${action}" == "a" ]; then
addUser ${username}
fi
done
"find_home_in_nfs.sh"(ホームの場所を見つけるためにすべてのNFSサーバーへの多くのSSH接続を実行します)を呼び出さずにスクリプトの単純化されたバージョンを再構築してみましたが、うまくいきました。
ただし、使用する必要がありますが変更できません。 whileループを操作する方法はありますか?
答え1
次の例のように、ループを大幅に簡素化できます。
while read username action
do
if [ "${action}" == "d" ]; then
echo "deleteUser ${username}"
elif [ "${action}" == "a" ]; then
echo "addUser ${username}"
fi
done < myFile
答え2
基本的な問題は、ssh
ほとんどのファイルを読むことです。read line
ファイルから最初の行を読み、次に(他の何よりも)stdinで未読実行を実行し、次にssh -n $nfsserver "rm -rf /home/${1}"
stdinで読み取らずに-n
実行するので、内容を読み取ることができるすべての内容(つまり、ファイル全体の残りの部分)を読みます。リモートコンピュータに送信すると無視されます。その後、次の反復が開始され、ファイルから読み取ろうとしますが、最後にあるのでループが終了します。ssh ldap "sudo deleteUser ${1}"
-n
read line
-n
追加のコマンド(および実行できるssh
他のコマンド)を追加することで、この問題を解決できます。ssh
そしてstdinで読むことができる他のすべてのコマンドに似たものを追加します</dev/null
。しかし、私は完全な混乱をスキップするためにstdin以外のコマンドから読み取るファイルを送信することを好みます。 FD#3を使用して送信および読み取る方法は次のとおりです。
while read line <&3; do
...
done 3<myFile
read
これをフィールド分割を処理する@fpmurphy1の提案と@Kusalanandaの次の使用と組み合わせますcase
。
while read username action <&3
do
case "$action" in
d) deleteUser "$username" ;;
a) addUser "$username" ;;
*) echo "Unknown action: $action on user $username" >&2 ;;
esac
done 3< myFile
ところで、一度に多数のユーザーを追加および削除する場合は、さらに最適化したいと思います。現在のバージョンでは、各サーバーで各ユーザーに対して別々のSSHセッションを開きます。各サーバーへの単一の接続を開き、その接続を介してすべてのユーザーを処理する方が高速です。欠点:注意しないと、エラー処理がより複雑になる可能性があります。
答え3
bash
連想配列を使用するより簡単なコード:
declare -A a=([a]=add [d]=delete)
while read username action; do
${a[$action]}User ${username}
done < myFile