現在のシェルを確認するcheckbashisms準拠の方法


18

.profileので、次のコードを使用して、ログインシェルが実際にBashである場合にのみBash関連のエイリアスと関数がソースされるようにします。

# If the current (login) shell is Bash, then
if [ "${BASH_VERSION:-}" ]; then
  # source ~/.bashrc if it exists.
  if [ -f "$HOME/.bashrc" ]; then
    . "$HOME/.bashrc"
  fi
fi

現在、シェル構成ファイル、スクリプト、および関数をバージョン管理下に置いています。また、最近、Bash固有の機能の恩恵を受けないカジュアルなBashismをシェルスクリプトから削除するプロセスを開始function funcname()しましたfuncname()。たとえば、に置き換えます。

シェルファイルリポジトリには、リポジトリ内の各ファイルでDebianのdevscriptsパッケージからユーティリティを実行するpre-commitフックを設定し、Bash固有の構文を誤って導入しないようにしました。ただし、これによりmyのエラーが発生します。checkbashismssh.profile

possible bashism in .profile line 51 ($BASH_SOMETHING):
if [ "${BASH_VERSION:-}" ]; then

私は、どのシェルが実行されているかをチェックする方法があり、それが警告をトリガーしないかどうか疑問に思っていましたcheckbashisms

POSIXによってリストされたシェル関連の変数のリストをチェックして、現在のシェルを表示するために使用できることを期待しました。また、インタラクティブなDashシェルで設定された変数を調べましたが、適切な候補を見つけることができませんでした。

現時点では、.profile処理対象から除外していますcheckbashisms。小さいファイルなので、手動で確認するのは難しくありません。ただし、問題を調査した後、実行中のシェル(または少なくともcheckbashisms失敗を引き起こさない方法)を判別するPOSIX準拠のメソッドがあるかどうかを知りたいと思います。


さらなる背景/説明

シェル構成ファイルをバージョン管理下に置く理由の1つは、現在ログインしているすべてのシステム(Cygwin、Ubuntu、およびCentOS(両方とも5および7、ユーザー用にActive Directoryを使用)で環境を構成することです)認証)。ほとんどの場合、X Windows /デスクトップ環境とリモートホスト用のSSH経由でログオンします。ただし、これは将来の証拠であり、システムの依存関係や他のツールへの依存を最小限に抑えたいと考えています。

checkbashismsは、シェル関連ファイルの構文の単純な自動健全性チェックとして使用しています。これは完璧なツールではありません。たとえば、command -vスクリプトでの使用について文句を言わないように、既にパッチを適用しています。調査中、プログラムの実際の目的は、2008年(または2013年の改訂版)ではなくPOSIX 2004に基づいたDebianポリシーへの準拠を確保することであることを学びました。


あなたがしていることは、POSIX準拠の異なる環境で全体を異なる方法で実行することである場合に、POSIX準拠になります。あなたの牛肉はチェックバシズムに基づいています。
ジル 'SO-悪であるのをやめる'

ちなみに、私の設定の移植性をチェックするためにcheckbashismsを使用したことは一度もありません。別のシステムで使用して確認します。
ジル 'SO-悪であるのをやめる'

2
ところで、ここでやっている特定のことのために、と(条件付き)の.bash_profile両方をソース.profileとするを書いてください.bashrc
ジル 'SO-悪であるのをやめる'

@Gillesのフィードバックをありがとう。これは、特定の問題に対する非常にエレガントなソリューションです。
アンソニーG-モニカの正義

回答:


16

きみの

# If the current (login) shell is Bash, then
if [ "${BASH_VERSION:-}" ]; then
  # source ~/.bashrc if it exists.
  if [ -f "$HOME/.bashrc" ]; then
    . "$HOME/.bashrc"
  fi
fi

コードは完全にPOSIXに準拠しており、現在実行していることをチェックする最良の方法ですbash。もちろん、$BASH_VERSION変数はbash固有ですが、それが特にそれを使用している理由です!実行していることを確認するにはbash

$BASH_VERSIONかどうかを設定されますbashように呼び出されますbashsh。あなたが実行していると主張したらbash、あなたは使用することができ[ -o posix ]、シェルは次のように呼び出されたことを示す指標としてshそのオプションがPOSIXLY_CORRECTが環境内にあるときにも設定されているかかかわらず、(bashと呼ばれる-o posix、または環境でのSHELLOPTS = POSIXで。ただし、これらすべての場合、bashとして呼び出されるかのように動作しますsh)。


もう一つの変数は、あなたの代わりに使用することができ$BASH_VERSION、それはcheckbashism渡さない限り、文句を言うとは思われない-xオプションがあります$BASH。これはまた、特定のものなbashので、実行中かどうかを判断するためにも使用できるはずですbash


また、実際にはの適切な使用法ではないと主張しcheckbashismsます。checkbashismsは、POSIXのスーパーセットであるDebianポリシーの仕様shに従って、移植可能なスクリプトを作成するのに役立つツールです。これは、へのシンボリックリンクがあるshシステムでスクリプトを作成する人々によって導入された非標準の構文を識別するのに役立ちます。shbash

A .profileはさまざまなシェルによって解釈されますが、その多くはPOSIXに準拠していません。通常、shログインシェルとしては使用しませんがzshfishなどのシェル、またはbashより高度なインタラクティブ機能を備えたシェルを使用します。

bashそしてzshshそれぞれのプロファイルセッションファイル(.bash_profile.zprofile)がPOSIXに準拠していない(特にzsh)として呼び出されていない場合、まだ読み取られている場合.profile

それはありませんので、POSIXはあなたがしたい構文.profileが、POSIX(用と互換性のある構文sh)、bashおよびzshBourneシェルも読み込むよう、あなたはそれらのシェル(おそらくはボーンを使用することをこれまでしている場合.profileが、一般的にLinuxベースのシステムで発見されていません)。

checkbashisms間違いなくあなたが見つける役立つだろうbashismsをしかしと互換性がありませんPOSIXの構文指摘しないかもしれないzshかをbash

ここで、bash特定のコード(対話型ログインシェルでbash読み取れないバグの回避策など)を使用する場合~/.bashrc、より良いアプローチは、それを~/.bash_profile行うことです(~/.profile共通セッションを置く場所の調達前または調達後に)初期化)。


checkbashisms使用される変数のため、これは合格しません。
トーマスディッキー

2
@ThomasDickey、はい、しかし、それはcheckbashismsレポートが無視されるべきケースです。これまでに示した他のすべてのソリューションは、かなり悪いです。
ステファンシャゼラス16年

@StéphaneChazelasあなたは、他のすべての解決策はもっと悪いと言います。$0この特定のケースに使用すると何が問題になりますか?
アンソニーG-モニカの正義

2
@AnthonyGeogheganそれはas shと呼ばれるbashとas と呼ばれる他のシェルを区別しませんsh
ジル 'SO-悪であるのをやめる'

またdash、別のbash以外のシェルがで誤って呼び出されたargv[0] == "bash"場合、誤検知が発生します。
ケビン

17

通常$0、この目的に使用します。リンクしたサイトでは次のようになります。

0
   (Zero.) Expands to the name of the shell or shell script.

とても簡単!$0シェルスクリプトの名前に使用することに慣れてきたため、現在のシェルを参照できることを忘れてしまいました。ありがとう!
アンソニーG-モニカの正義

1
いつものように、この規則はすべての行儀の良いプログラムによって尊重されますが、悪意のあるプログラムはexec、呼び出しプログラムが引数として渡される文字列とは別に実行されるバイナリを識別することができるため、家族からのさまざまなシステムコールを使用してあなたを混乱させることができます0.
dmckee

それは.profileで機能します:)かわいい
ロブ

5

通常、SHELL環境変数はデフォルトのシェルを示します。手動で.bashrcファイルを入手する必要はありません(更新ページを参照)。bashは、$ HOMEディレクトリにあることを確認するだけで自動的にこれを行う必要があります。

他のオプションは次のようなことです:

 ps -o cmd= $$

現在のプロセスのコマンド(引数なし、値なしの=は列ヘッダーを表示しません)を示します。出力例:

 $ps -o cmd= $$
 bash
 $sh
 $ps -o cmd= $$
 sh

更新:

私は訂正します!:)

.bashrcは、以下のコメントおよび/programming/415403/whats-the-difference-between-bashrc-bash-profile-and-environmentで述べられているように、常にソースとは限りません

したがって、.bashrcを.bash_profileに移動し、テストを行わなくてもそれが機能するかどうかを確認できます。そうでない場合は、上記のテストがあります。


1
.bashrc実際にはログインシェルからではなく、.profile(存在する場合)または存在し.bash_profileます。 SHELLがPOSIXによって指定されておらず、残念ながら、のcmdフォーマットオプションもありませんps
アンソニーG-モニカの正義

1
これは私が使用するものですが、悪意のある操作の対象にもなります。
dmckee

ps -o cmd= $$ほぼすべての場所で機能するはず$SHELLですが、変数は完全に無関係です。これはユーザーのデフォルトシェルであり、現在実行されているシェルやシェルスクリプトを実行しているシェルには関係ありません。
テルドン

2
そうでもない 多くのシェルは~/.profile、ログインシェルとして起動されると読み取ります。だから、例えば、あなた$SHELLはそうでcshあり、あなたは走るbash -l。これにより、ログインシェルとしてbashが開始されるため、と表示され~/.profileます$SHELLが、まだを指しますcsh。さらに、.profile別のスクリプトによって明示的にソースされる場合があります。OPは最大限の堅牢性を求めているため、あらゆる種類のケースを考慮する必要があります。いずれに$SHELLしても、現在実行中のシェルに関する有用な情報は提供しません。
テルドン

2
FWIW、私はあまりにも修正スタンド-についてのSHELLPOSIXによって指定されていない:pubs.opengroup.org/onlinepubs/9699919799/basedefs/...
アンソニー・G -モニカのための正義の

4

質問は、ユーザーのログインシェルと現在のシェルをなだめるような方法で尋ねcheckbashismsます。それがユーザーがログインしたシェルである場合/etc/passwd、たとえば、

MY_UID=$(id -u)
MYSHELL=$(awk -F: '$3 == '$MY_UID'{ print $7; }' </etc/passwd )

もちろん、ユーザーはログイン後に新しいシェルを開始できます。もちろん、一方がbashでもう一方がそうでない場合、bashの環境変数のテストは役に立たないかもしれません。

ファイルgetentだけでなく使用したい人もいるかもしれませんpasswd(ただし、それは質問の範囲内ではありません)。

LDAPに関するコメントとの提案に基づいてlogname、この代替形式を使用できます。

MY_NAME=$(logname)
MYSHELL=$(getent passwd | awk -F: '$1 ~ /^'$MY_NAME'$/ {print $7;}' )

テスト中に、lognameリダイレクトされた入力が気に入らないことに気付きました(そのため、式を分割したままにしました)。クイックチェックショーgetentは、上記のプラットフォームで動作するはずです(ただし、元の質問で提供されているはずです)。


1
ユーザーデータベースが/ etc / passwd(LDAP / NIS / mysql ...ではない)にあり、ユーザーIDごとにユーザー名が1つだけであると仮定します。(最初の列をチェックする方が良いでしょう$(logname))。
ステファンシャゼル16年

iirc、POSIXは必要なユーティリティを定義していません(または、回答で使用していました)。使用するid変数またはユーザーが変更可能な変数は、別の選択肢です。
トーマスディッキー

1
私が言ったことに注意してください$(logname)、ではありません$LOGNAME。ユーザーIDとログインシェルは両方とも、ログイン時に使用されたユーザー名から派生します。ユーザーIDごとにユーザー名が1つしかないシステムを除き、ユーザーIDからログインシェルに戻ることはできません。または、IOW、ユーザーデータベースのプライマリキーは、uidではなくユーザー名です。
ステファンシャゼラス16年

@ThomasDickeyに、異なる視点からの回答をありがとう。ただし、それは私が考えていたよりも少し複雑です(jimmijの回答やStéphaneの回答に似ています)。シェル構成ファイルをバージョン管理下に置く理由の1つは、現在ログインしているすべてのシステム(Cygwin、Ubuntu、CentOS(両方とも5と7、ユーザー用にActive Directoryを使用)で環境を構成することです)認証)。そのため、私はロジックをできるだけシンプルに保つことを好みます。
アンソニーG-モニカの正義
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.