スクリプトは、bashまたはdashのどちらで実行されているかをどのように判断できますか?


13

2つの異なるシステムでOneiricの新規インストール(つまり、アップグレードではない)を実行しており、一見関連する問題の同じセットに遭遇しています。

最も不満なのは、Mac OS Xから持ってきた.profileと.bashrcを使用すると、LightDMを介してXにログインするとすぐにログアウトされることです。これは、「/ bin / sh」を実行すると、/ bin / dashとして動作しますが、$ SHELL変数が/ bin / bashに設定されているという事実が原因であると考えています。

外挿

私は巨大.bashrcです。必要に応じてここで確認できますが、bashismでいっぱいであるという事実と、xterm内または仮想コンソール上でエラーなしで動作するという事実は別として、その内容はおそらく関連性がありません。

私の.profile見た目は次のようになります(略称)

case $SHELL in 
*bash*)
    if [ -f $HOME/.bashrc -a -r $HOME/.bashrc ]; then
        . $HOME/.bashrc
    fi
    ;;
esac

LightDMを介してXにログインしようとすると、すぐにログアウトされます。.xsession-errors.bashrc に関連して次のようなエラーが表示されます(略称):

/home/mrled/.bashrc: 103: [[: not found
[: 103: Linux: unexpected operator
[: 274: -P :: unexpected operator
/home/mrled/.bashrc: 520: complete: not found

前述したように、仮想コンソールからbashを実行すると、これらのエラーは発生しません。さらに、.profileを削除すると、Xに問題なくログインできます。(仮想コンソールにログインして、動作startxするXセッションを開始することもできますが、これはもちろん長期的な解決策ではありません。)

しかし、私は私が実行した場合ことを発見し/bin/sh -l、私はないエラーが発生します。以下にセッションの例を示します(注:簡略化したbashプロンプトbash>、およびshプロンプトは単に$):

bash> echo $SHELL
/bin/bash
bash> echo $BASH_VERSION
4.2.10(1)-release
bash> /bin/sh -l
/home/mrled/.bashrc: 103: [[: not found
[: 103: Linux: unexpected operator
[: 274: -P :: unexpected operator
/home/mrled/.bashrc: 520: complete: not found
$ echo $SHELL
/bin/bash
$ echo $BASH_VERSION

$

Q1:なぜこれが起こっているのですか?

/ bin / shがbashではなくdashを指すようになったことを理解していますが、それが本当なら、なぜ$SHELLまだ戻っているの/bin/bashでしょうか?

Q2:回避策はありますか?

これを回避する方法はありますか?プロファイルを.bashrcにロードしたままにして、ログインシェルと非ログインシェルの両方で同じ環境を取得したいのですが、明らかに、bashを装った/ bin / shではなくbashのみにロードしたいのです。

上記の$ BASH_VERSION変数の内容の違いに気づいたかもしれません。私の.profileを次のようにラップしてみました:

if [ -n $BASH_VERSION ]; then
    # the rest of my .profile as above
fi

この-nテストは、文字列の長さがゼロ以外の場合にのみtrueを返す必要がありますが、上記のセッション/bin/sh -lでは、その下で実行しているときに$ BASH_VERSIONの空の文字列を返します。 、テストに合格しました!それは、私の.bashrcのソースに進み、以前と同じエラーを私に与えます。

今、私は本当に混乱しています。


dash -l$SHELL持つことも示していることに注意してください/bin/bash
スコットセブランス

3
$SHELL/etc/passwd(またはgetent passwd)の最後のフィールドが言うものは何でも。
追って通知があるまで一時停止します。

@DennisWilliamson ありがとう、それは私が正しい答えを見つけるために知る必要があったものです。
ミカRレッドベター

あなたはそれを間違っています。非bash固有の環境を~/.profile、bash固有のものをに配置し~/.bashrc~/.bash_profile両方をソースにする必要があります。
nyuszika7h

回答:


12

あなたはあなたのため$BASH_VERSIONdash仕事で空白であるという事実を作ることができます:

if [ "$BASH_VERSION" = '' ]; then
    echo "This is dash."
else
    echo "This is bash."
fi

2
「x」テクニックは古風で、古代のシェルでのみ必要です。使用if [ "$BASH_VERSION" = '' ]
さらに通知があるまで一時停止します。

@DennisWilliamson:ありがとう。あなたのテクニックはBashに固有のものだと思っていましたが、Dashに置いただけでうまくいきました。回答を編集しました。
スコットセベランス

または単に使用する-nか、何もしません。(ただし、+ = ''
1。

5

使用する変数BASH_VERSIONに引用符を使用するだけです-n

if [ -n "$BASH_VERSION" ];then
 echo "this is bash"; 
else 
 echo "this is dash";
fi

1
以来[ "$EMPTY_STRING" ]評価する偽、あなたも必要ありません-n。変数を引用するだけです。
ジェベル

2

を使用/proc/[PID]/cmdlineして、スクリプトの実行対象を確認し、スクリプトの内容をテストします。$$変数には、私たちに実行しているシェルのPIDを与えるだろう。したがって、このようなスクリプトを作成できます。

#!/bin/bash
if grep -q 'bash' /proc/$$/cmdline ;
then
    echo "This is bash"
else
    echo "This is some other shell"
fi

同じスクリプトのテストを次に示します。

$> bash test_script.sh                                                                                                
This is bash
$> dash test_script.sh                                                                                                
This is some other shell

これはMacでは機能しません。$ BASH_VERSIONを確認してください。
オースティンバーク

2
@AustinBurkはMacで動作する必要はありません。これはAsk Ubuntuです。
TheWanderer

@ Zacharee1ああ、それは気にしない、私は注意を払っていなかった:、)
オースティンバーク

これを意図したものから編集したくありませんが、この方法の制限について言及することをお勧めします。Bashのbash名前は必要ありません。bash別の名前のシンボリックリンクを介して実行可能ファイルが実行されることは珍しくありません。通常、そのBashを検討したいと思うでしょう。また、パターンはの任意の場所一致します/proc/$$/cmdline、これは修正可能ですが、引数in cmdlineはヌル文字で区切られていることに注意してください。grep -qE '(^|/)bash$'は動作するはずですが、引数がの場合は偽陽性になりますbash
エリアケイガン

@EliahKagan私の答えはいつでも自由に編集してください-あなたは十分な専門知識を持っているので、あなたの編集は改善のみを提供できることを知っています。答えは、私が今よりも貝でずっと環境に優しいときに書かれました。
セルギーKolodyazhnyy
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.