web-dev-qa-db-ja.com

現在作業中のシェルを確認する方法

現在作業中のシェルを確認するにはどうすればよいですか。

psコマンドの出力だけで十分ですか?

どのようにしてこれを異なる種類のUNIXで行うことができますか?

544
josh
  • 現在のシェルの実行可能ファイルのnameを見つけるには3つの方法があります。

    シェルの実行可能ファイルが/bin/shである場合、3つのアプローチすべてがだまされる可能性がありますが、たとえば、実際にはbashという名前に変更されています(よくあることです)。

    psの出力がどうなるかという2つ目の質問には、 "常にではない"と答えます。

    1. echo $0 - プログラム名を表示します。Shellの場合は実際のシェルです。

    2. ps -ef | grep $$ | grep -v grep - 実行中のプロセスのリストから現在のプロセスIDを探します。現在のプロセスがシェルであるので、それが含まれます。

      psのリストにShellのプロセスIDと同じ番号が含まれている他のプロセス、特にそのIDが小さい#の場合(例えばShellのPIDが "5"の場合)、 "Java5"というプロセスが見つかるかもしれません。同じgrepの出力の中の "または" Perl5 "!) シェル名に頼れないことに加えて、これが "ps"アプローチの2番目の問題です。

    3. echo $Shell - 現在のシェルへのパスは、任意のシェルのShell変数として格納されます。これに対する注意点は、シェルをサブプロセスとして明示的に起動した場合(例えば、あなたのログインシェルではない場合)、代わりにあなたのログインシェルの値を取得するということです。それが可能な場合は、psまたは$0アプローチを使用してください。


  • ただし、実行可能ファイルが実際のシェルと一致しない場合(例:/bin/shが実際にはbashまたはkshの場合)、ヒューリスティックが必要です。ここでは様々なシェルに固有のいくつかの環境変数は次のとおりです。

    • $versionがtcshに設定されている

    • $BASHがbashに設定されている

    • cshまたはtcshで$Shell(小文字)が実際のシェル名に設定されている

    • $ZSH_NAMEがzshに設定されている

    • kshは$PS3$PS4が設定されていますが、通常のBourne Shell(sh)は$PS1$PS2しか設定されていません。私たちは、Solarisのツゲにインストールされているshksh間envionmental変数のセット全体での唯一の違いは$ERRNO$FCEDIT$LINENO$PPID$PS3$PS4$RANDOM$SECONDS$TMOUTである - これは、一般的に区別することが困難なように思えます。

700
DVK

ps -p $$

ps -efgrepを含む解決策が( ps のためのPOSIXオプションをサポートするすべてのUnix版で)行うことができる場所ならどこでも動作するはずです。

84

試します

ps -p $$ -oargs=

または

ps -p $$ -ocomm=
35

ユーザがbashでスクリプトを起動していることを確認したいだけの場合は、次のようにします。

if [ ! -n "$BASH" ] ;then echo Please run this script $0 with bash; exit 1; fi
23
Peter Lamberg

あなたが試すことができます:

ps | grep `echo $$` | awk '{ print $4 }'

または

echo $Shell
19
karlphillip

$Shellは必ずしも現在のシェルを表示する必要はありません。起動されるデフォルトのシェルのみが反映されます。

上記をテストするには、bashがデフォルトのシェルであるとし、echo $Shellを試してから、同じ端末で他のシェル(kshなど)に入って$Shellを試してください。どちらの場合も結果はbashになります。

現在のシェルの名前を取得するには、cat /proc/$$/cmdlineを使用します。そして、readlink /proc/$$/exeによってシェル実行可能ファイルへのパスを指定します。

11
sr01853

psは最も信頼できる方法です。 Shell envarは確実に設定されるわけではなく、設定されていても簡単になりすまし可能

9
ennuikiller

現在のシェルを見つけるための簡単なトリックがあります。ランダムな文字列を入力するだけです(これはコマンドではありません)。それは失敗して「見つかりません」というエラーを返しますが、行の先頭にはどのシェルかを表示します。

ksh: aaaaa: not found [No such file or directory]
bash: aaaaa: command not found
8
user5659949

私はさまざまな方法を試してみましたが、私にとって最良の方法は次のとおりです。

ps -p $$

それは Cygwin の下でも動作し、PID greppingとして誤検知を生成することはできません。いくらかのクリーニングを行うと、実行可能ファイル名( Cygwin のパスの下)だけが出力されます。

ps -p $$ | tail -1 | awk '{print $NF}'

あなたはそれを暗記する必要はありませんので、あなたは関数を作成することができます:

# print currently active Shell
shell () {
  ps -p $$ | tail -1 | awk '{print $NF}'
}

...そしてShellを実行してください。

DebianとCygwinの下でテスト済み。

親プロセスを印刷する私の変種。

ps -p $$ | awk '$1 == PP {print $4}' PP=$$

'awk'があなたに代わってそれを実行できるのに、なぜ不要なアプリケーションを実行するのですか?

4
Matthew Stier

/bin/shがPOSIX標準をサポートし、システムにlsofコマンドがインストールされている場合-lsofの代わりにpid2pathを使用できます-使用することもできます(または適応)完全なパスを出力する次のスクリプト:

#!/bin/sh
# cat /usr/local/bin/cursh
set -eu
pid="$$"

set -- sh bash zsh ksh ash dash csh tcsh pdksh mksh fish psh rc scsh bournesh wish Wish login

unset echo env sed ps lsof awk getconf

# getconf _POSIX_VERSION  # reliable test for availability of POSIX system?
PATH="`PATH=/usr/bin:/bin:/usr/sbin:/sbin getconf PATH`"
[ $? -ne 0 ] && { echo "'getconf PATH' failed"; exit 1; }
export PATH

cmd="lsof"
env -i PATH="${PATH}" type "$cmd" 1>/dev/null 2>&1 || { echo "$cmd not found"; exit 1; }

awkstr="`echo "$@" | sed 's/\([^ ]\{1,\}\)/|\/\1/g; s/ /$/g' | sed 's/^|//; s/$/$/'`"

ppid="`env -i PATH="${PATH}" ps -p $pid -o ppid=`"
[ "${ppid}"X = ""X ] && { echo "no ppid found"; exit 1; }

lsofstr="`lsof -p $ppid`" || 
   { printf "%s\n" "lsof failed" "try: Sudo lsof -p \`ps -p \$\$ -o ppid=\`"; exit 1; }

printf "%s\n" "${lsofstr}" | 
   LC_ALL=C awk -v var="${awkstr}" '$NF ~ var {print $NF}'
3
carlo
echo $$ # Gives the Parent Process ID 
ps -ef | grep $$ | awk '{print $8}' #use the PID to see what the process is.

http://www.unix.com/unix-dummies-questions-answers/10390-how-do-you-know-what-your-current-Shell.html から

2
Moisei

これはあまりきれいな解決策ではありませんが、あなたが望むことをします。

私は、この古き良き2015年に答えが少し遅れていることを理解していますが、...

#MUST BE SOURCED..
getshell() {
    local Shell="`ps -p $$ | tail -1 | awk '{print $4}'`"

    shells_array=(
    # It is important that the shells are listed by the decrease of their length name.
        pdksh
        bash dash mksh
        zsh ksh
        sh
    )

    local suited=false
    for i in ${shells_array[*]}; do
        if ! [ -z `printf $Shell | grep $i` ] && ! $suited; then
            Shell=$i
            suited=true
        fi
    done

    echo $Shell
}
getshell

これで$(getshell) --version.を使うことができます

ただし、これはksh風のシェルでのみ機能します。

1
theoden

Mac OS X(&FreeBSD)の場合:

ps -p $$ -axco command | sed -n '$p' 
1
zaga

私の解決策:

ps -o command | grep -v -e "\<ps\>" -e grep -e tail | tail -1

これは異なるプラットフォームやシェル間で移植性があるはずです。他の解決策のようにpsを使いますが、sedawkに頼らず、配管からのゴミやpsを取り除き、シェルが常に最後のエントリになるようにします。こうすれば、移植性のないPID変数に頼る必要も、正しい行と列を選ぶ必要もありません。

私は、bash、zsh、およびfishを使ってDebianとMacOSをテストしました(これは異なるPID変数を使うため、fishの表現を変更しないとこれらの解決策のほとんどではうまくいきません)。

1
wickles

"ps"の出力からPIDを取得する必要はありません。これは、/ procディレクトリ構造から任意のPIDについてそれぞれのコマンドラインを読み取ることができるためです。

echo $(cat /proc/$$/cmdline)

しかし、それは単に以下のようなものではありません。

echo $0

実際の名前とは異なるシェルを実行する場合の考えの1つは、以前に取得した名前を使用してシェルにバージョンを要求することです。

<some_Shell> --version

shは終了コード2で失敗するようですが、他のものは便利なものを提供します(ただし、それらがないため、すべてを検証することはできません)。

$ sh --version
sh: 0: Illegal option --
echo $?
2
1
ajaaskel

シェルがDASH/BASHを使用しているかどうかを知るために、次の手順を実行します。

1) ls –la/bin/sh 、結果が /bin/sh - >/bin/bash ==>の場合、シェルはBASHを使用します。

結果が /bin/sh - >/bin/dash ==>の場合、シェルはDASHを使用しています。

BASHからDASHへ、またはその逆に変更したい場合は、以下のコードを使用してください。 ln -s/bin/bash/bin/sh

注:上記のコマンドで/ bin/shがすでに存在するというエラーが表示された場合は、/ bin/shを削除してやり直してください。

1
Shiva

Bash(の特定のバージョン)を実行していることを確認したいだけの場合は、$BASH_VERSINFO配列変数を使用するのが最善の方法です。 (読み取り専用の)配列変数としては環境に設定できないので、(あれば)現在のシェルから来ていることを確認できます。ただし、shとして起動したときのBashの動作は異なるため、環境変数$BASHの末尾が/bashで終わっていることも確認する必要があります。

-(アンダースコアではありません)の関数名を使用し、連想配列(Bash 4で追加)に依存するスクリプトで、私は次の健全性チェックを行います(役に立つユーザーエラーメッセージ付き)。

case `eval 'echo $BASH@${BASH_VERSINFO[0]}' 2>/dev/null` in
    */bash@[456789])
        # Claims bash version 4+, check for func-names and associative arrays
        if ! eval "declare -A _ARRAY && func-name() { :; }" 2>/dev/null; then
            echo >&2 "bash $BASH_VERSION is not supported (not really bash?)"
            exit 1
        fi
        ;;
    */bash@[123])
        echo >&2 "bash $BASH_VERSION is not supported (version 4+ required)"
        exit 1
        ;;
    *)
        echo >&2 "This script requires BASH (version 4+) - not regular sh"
        echo >&2 "Re-run as \"bash $CMD\" for proper operation"
        exit 1
        ;;
esac

最初のケースでは、やや妄想的な機能チェックを省略して、将来のbashバージョンに互換性があると仮定するだけでも構いません。

1
Alex Dupuy

どの答えもfishシェルではうまくいきませんでした(変数$$$0はありません)。

これは私には有効です(shbashfishkshcshtruetcshzsh、openSUSE 13.2でテスト済み)。

ps | tail -n 4 | sed -E '2,$d;s/.* (.*)/\1/'

このコマンドはbashのような文字列を出力します。ここではpstail、およびsedのみを使用しています(GNU範囲を除く、それをチェックするために--posixを追加してみてください)。それらはすべて標準のPOSIXコマンドです。私はtailを削除できると確信していますが、私のsed fuはこれを行うのに十分なほど強力ではありません。

私には、このソリューションはOS Xでは機能しないため、あまり移植性がないと思われます。

1
rominf

シェルとそれに対応するバージョンを見つける方法はたくさんあります。これが私のために働いたいくつかです。

ストレートフォワード

  1. $> echo $ 0 (プログラム名を教えてください。私の場合、出力は -bash でした)
  2. $> $ Shell (これでシェルに入り、プロンプトでシェルの名前とバージョンが表示されます。私の場合は bash3.2 $
  3. $> echo $ Shell (これで実行可能なパスがわかります。私の場合は /bin/bash
  4. $> $ Shell --version (これにより、ライセンスタイプを含むShellソフトウェアに関する完全な情報が得られます)

ハッキングなアプローチ

$> *******(一連のランダムな文字を入力すると、出力にシ​​ェル名が表示されます。私の場合は -bash:chapter2-a-sample-isomorphic-app:command not found

1
Devang Paliwal

下記のコマンドを使用してください。

 # ps -p $$ | tail -1 | awk '{print $4}'
0
Ranjithkumar T