【Bash】テキストファイルwhileループ + ssh の落とし穴

シェルスクリプトのwhileループ内でssh繋いで何かやるものを書いたら、 どうやってもループが1回目だけで終わってしまった。

cat ${INVENTORY_FILE} | while read -r host port user passwd; do
            .
            .
            .

    sshpass -e \
        ssh \
            -oPubkeyAuthentication=no \
            -oConnectTimeout=10 \
            -oConnectionAttempts=3 \
            -oStrictHostKeyChecking=no \
            -l ${SSH_USER} \
            -p ${SSH_PORT} \
            ${SSH_HOST} \
            ${SSH_CMD}

            .
            .
            .
done

最初、sshpass(1) – Linux man pageBugs セクションに stdin がウンタラカンタラと書いてあったので、sshpass が標準入力で何か悪さしてるのかと推測してた。

しかし、このstackoverflowの回答によると、 悪さしてたのは実は ssh の方というオチだった……

記載通りに ssh コマンドへ -n オプションを追加して解決した。

cat ${INVENTORY_FILE} | while read -r host port user passwd; do
            .
            .
            .

    sshpass -e \
        ssh -n \
            -oPubkeyAuthentication=no \
            -oConnectTimeout=10 \
            -oConnectionAttempts=3 \
            -oStrictHostKeyChecking=no \
            -l ${SSH_USER} \
            -p ${SSH_PORT} \
            ${SSH_HOST} \
            ${SSH_CMD}

            .
            .
            .
done

-n Redirects stdin from /dev/null (actually, prevents reading from stdin). This must be used when ssh is run in the background. A common trick is to use this to run X11 programs on a remote machine. For example, ssh -n shadows.cs.hut.fi emacs & will start an emacs on shadows.cs.hut.fi, and the X11 connection will be automatically forwarded over an encrypted channel. The ssh program will be put in the background. (This does not work if ssh needs to ask for a password or passphrase; see also the -f option.)

ssh(1) – Linux man page より