Help us understand the problem. What is going on with this article?

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

More than 3 years have passed since last update.

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  2月 10 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 を使わない。

tsubasaogawa
温故知新
openwork
転職・就職のための情報プラットフォーム「OpenWork」の企画・開発・運用をしています。
https://vorkers.jp/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away