.bashrc で exit するスクリプトを source しちゃったときの対処法

  • 7
    いいね
  • 0
    コメント

tl;dr

  • source で読み込んだスクリプト内で exit すると、呼び出し元スクリプトごと終了する
  • ↑ を .bashrc でやってしまうとログインができなくなる
  • そうなってしまったらログイン時に Ctrl+C を連打する

背景

自作の便利スクリプトをサーバーログイン時 (厳密には Bash 起動時) に実行させるようにしました。

[togawa@remote01 ~]$ echo 'source ./myscript.sh' >> ./.bashrc

このサーバーを remote01 とし、ログイン元サーバーを local01 とします。

問題

一度 remote01 からログアウトし、再度ログインしたところ そのままログアウト されてしまいました。

[togawa@remote01 ~]$ logout
Connection to xxx.xx.x.xx closed.

[togawa@local01 ~]$ ssh remote01
togawa@xxx.xx.x.xx's password: 
Last login: Fri Feb 10 19:04:02 2017 from xxx.xx.x.xx
Connection to xxx.xx.x.xx closed.
[togawa@local01 ~]$ 

原因は以下の2つが成り立ってしまったためです。

  • スクリプトを .bashrc の source から呼び出していること
  • スクリプト中で exit していること

試したこと

ssh rm

このままではサーバーにログインができません。
とはいえ、 .bashrc が発動する前に問題のスクリプト (myscript.sh) を消せれば良いはずです。
ssh に引数を与えるとそれをコマンドとして実行してくれるので、 rm を渡してみます。

[togawa@local01 ~]$ ssh remote01 rm myscript.sh
togawa@xxx.xx.x.xx's password: 
Connection to xxx.xx.x.xx closed.
[togawa@local01 ~]$ 

結果はだめ。

scp

ssh がだめなら scp はどうだ、ということで空のファイルを転送してスクリプトを 0 byte にする作戦です。

[togawa@local01 ~]$ touch myscript.sh
[togawa@local01 ~]$ ls -l myscript.sh
-rw-r--r-- 1 togawa togawa 0  210 19:48 myscript.sh

[togawa@local01 ~]$ scp ./myscript.sh remote01:~
togawa@xxx.xx.x.xx's password: 
Connection to xxx.xx.x.xx closed.
[togawa@local01 ~]$ 

これもだめでした。 ssh/scp では律儀に .bashrc が読み込まれてしまいます。

Bash の起動を止める

ServerFault という Stackoverflow 風味のサイトでは、「.bashrc がロードされる前に Ctrl + C で Bash の起動を中止させるといいよ」という回答がありました。
http://serverfault.com/questions/206544/i-screwed-up-exit-in-bashrc

ssh 実行 → ログイン先サーバーで bash 起動 → (*) → .bashrc ロード
↑ の (*) のタイミングで Ctrl + C を叩け、とのこと。タイミングがシビアそう。

ssh にデバッグモードの -v オプションをつけてやってみました。
確かにコツが必要でしたが、成る程、何度かやったらうまくいきました。


[togawa@local01 ~]$ ssh -v remote01
OpenSSH_4.3p2, OpenSSL 0.9.8e-fips-rhel5 01 Jul 2008
debug1: Reading configuration data /home/togawa/.ssh/config
debug1: Applying options for remote01
debug1: Reading configuration data /etc/ssh/ssh_config
debug1: Applying options for *
debug1: Connecting to xxx.xx.x.xx [xxx.xx.x.xx] port 22.
debug1: Connection established.
debug1: identity file /home/togawa/.ssh/identity type -1
debug1: identity file /home/togawa/.ssh/id_rsa type 1
debug1: identity file /home/togawa/.ssh/id_dsa type -1
debug1: loaded 3 keys
debug1: Remote protocol version 2.0, remote software version OpenSSH_6.6.1
debug1: match: OpenSSH_6.6.1 pat OpenSSH*
debug1: Enabling compatibility mode for protocol 2.0
debug1: Local version string SSH-2.0-OpenSSH_4.3
debug1: SSH2_MSG_KEXINIT sent
debug1: SSH2_MSG_KEXINIT received
debug1: kex: server->client aes128-ctr hmac-md5 none
debug1: kex: client->server aes128-ctr hmac-md5 none
debug1: SSH2_MSG_KEX_DH_GEX_REQUEST(1024<1024<8192) sent
debug1: expecting SSH2_MSG_KEX_DH_GEX_GROUP
debug1: SSH2_MSG_KEX_DH_GEX_INIT sent
debug1: expecting SSH2_MSG_KEX_DH_GEX_REPLY
debug1: Host 'xxx.xx.x.xx' is known and matches the RSA host key.
debug1: Found key in /home/togawa/.ssh/known_hosts:42
debug1: ssh_rsa_verify: signature correct
debug1: SSH2_MSG_NEWKEYS sent
debug1: expecting SSH2_MSG_NEWKEYS
debug1: SSH2_MSG_NEWKEYS received
debug1: SSH2_MSG_SERVICE_REQUEST sent
debug1: SSH2_MSG_SERVICE_ACCEPT received
debug1: Authentications that can continue: publickey,password
debug1: Next authentication method: publickey
debug1: Trying private key: /home/togawa/.ssh/identity
debug1: Offering public key: /home/togawa/.ssh/id_rsa
debug1: Authentications that can continue: publickey,password
debug1: Trying private key: /home/togawa/.ssh/id_dsa
debug1: Next authentication method: password
togawa@xxx.xx.x.xx's password: 
debug1: Authentication succeeded (password).
debug1: channel 0: new [client-session]
debug1: Entering interactive session.
debug1: Sending environment.
debug1: Sending env LANG = ja_JP.UTF-8
Last login: Fri Feb 10 19:30:13 2017 from xxx.xxx.x.xx
^C-bash-4.2$ ^C
-bash-4.2$ ^C
-bash-4.2$ ^C
-bash-4.2$ ^C
-bash-4.2$ ^C
-bash-4.2$ 
-bash-4.2$ ls
myscript.sh
-bash-4.2$ rm myscript.sh 
-bash-4.2$ ls
-bash-4.2$ 
-bash-4.2$ 

Bash キャンセル (各ゲーっぽい) が成功すると $PS1 が読み込まれていない、すなわち .bashrc が読み込まれていないことがわかります。
これによりログイン先サーバーで操作が可能になるので、問題のスクリプトを rm すれば万事解決です。

教訓

シェルスクリプトではむやみに source を使わない。