現在作業中のシェルを確認するにはどうすればよいですか。
ps
コマンドの出力だけで十分ですか?
どのようにしてこれを異なる種類のUNIXで行うことができますか?
現在のシェルの実行可能ファイルのnameを見つけるには3つの方法があります。
シェルの実行可能ファイルが/bin/sh
である場合、3つのアプローチすべてがだまされる可能性がありますが、たとえば、実際にはbash
という名前に変更されています(よくあることです)。
ps
の出力がどうなるかという2つ目の質問には、 "常にではない"と答えます。
echo $0
- プログラム名を表示します。Shellの場合は実際のシェルです。
ps -ef | grep $$ | grep -v grep
- 実行中のプロセスのリストから現在のプロセスIDを探します。現在のプロセスがシェルであるので、それが含まれます。
ps
のリストにShellのプロセスIDと同じ番号が含まれている他のプロセス、特にそのIDが小さい#の場合(例えばShellのPIDが "5"の場合)、 "Java5"というプロセスが見つかるかもしれません。同じgrep
の出力の中の "または" Perl5 "!) シェル名に頼れないことに加えて、これが "ps"アプローチの2番目の問題です。
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のツゲにインストールされているsh
とksh
間envionmental変数のセット全体での唯一の違いは$ERRNO
、$FCEDIT
、$LINENO
、$PPID
、$PS3
、$PS4
、$RANDOM
、$SECONDS
、$TMOUT
である - これは、一般的に区別することが困難なように思えます。
ps -p $$
ps -ef
とgrep
を含む解決策が( ps
のためのPOSIXオプションをサポートするすべてのUnix版で)行うことができる場所ならどこでも動作するはずです。
試します
ps -p $$ -oargs=
または
ps -p $$ -ocomm=
ユーザがbashでスクリプトを起動していることを確認したいだけの場合は、次のようにします。
if [ ! -n "$BASH" ] ;then echo Please run this script $0 with bash; exit 1; fi
あなたが試すことができます:
ps | grep `echo $$` | awk '{ print $4 }'
または
echo $Shell
$Shell
は必ずしも現在のシェルを表示する必要はありません。起動されるデフォルトのシェルのみが反映されます。
上記をテストするには、bash
がデフォルトのシェルであるとし、echo $Shell
を試してから、同じ端末で他のシェル(kshなど)に入って$Shell
を試してください。どちらの場合も結果はbashになります。
現在のシェルの名前を取得するには、cat /proc/$$/cmdline
を使用します。そして、readlink /proc/$$/exe
によってシェル実行可能ファイルへのパスを指定します。
psは最も信頼できる方法です。 Shell envarは確実に設定されるわけではなく、設定されていても簡単になりすまし可能
現在のシェルを見つけるための簡単なトリックがあります。ランダムな文字列を入力するだけです(これはコマンドではありません)。それは失敗して「見つかりません」というエラーを返しますが、行の先頭にはどのシェルかを表示します。
ksh: aaaaa: not found [No such file or directory]
bash: aaaaa: command not found
私はさまざまな方法を試してみましたが、私にとって最良の方法は次のとおりです。
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'があなたに代わってそれを実行できるのに、なぜ不要なアプリケーションを実行するのですか?
/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}'
echo $$ # Gives the Parent Process ID
ps -ef | grep $$ | awk '{print $8}' #use the PID to see what the process is.
これはあまりきれいな解決策ではありませんが、あなたが望むことをします。
私は、この古き良き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風のシェルでのみ機能します。
Mac OS X(&FreeBSD)の場合:
ps -p $$ -axco command | sed -n '$p'
私の解決策:
ps -o command | grep -v -e "\<ps\>" -e grep -e tail | tail -1
これは異なるプラットフォームやシェル間で移植性があるはずです。他の解決策のようにps
を使いますが、sed
やawk
に頼らず、配管からのゴミやps
を取り除き、シェルが常に最後のエントリになるようにします。こうすれば、移植性のないPID変数に頼る必要も、正しい行と列を選ぶ必要もありません。
私は、bash、zsh、およびfishを使ってDebianとMacOSをテストしました(これは異なるPID変数を使うため、fishの表現を変更しないとこれらの解決策のほとんどではうまくいきません)。
"ps"の出力からPIDを取得する必要はありません。これは、/ procディレクトリ構造から任意のPIDについてそれぞれのコマンドラインを読み取ることができるためです。
echo $(cat /proc/$$/cmdline)
しかし、それは単に以下のようなものではありません。
echo $0
実際の名前とは異なるシェルを実行する場合の考えの1つは、以前に取得した名前を使用してシェルにバージョンを要求することです。
<some_Shell> --version
shは終了コード2で失敗するようですが、他のものは便利なものを提供します(ただし、それらがないため、すべてを検証することはできません)。
$ sh --version
sh: 0: Illegal option --
echo $?
2
シェルが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を削除してやり直してください。
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バージョンに互換性があると仮定するだけでも構いません。
どの答えもfish
シェルではうまくいきませんでした(変数$$
や$0
はありません)。
これは私には有効です(sh
、bash
、fish
、ksh
、csh
、true
、tcsh
、zsh
、openSUSE 13.2でテスト済み)。
ps | tail -n 4 | sed -E '2,$d;s/.* (.*)/\1/'
このコマンドはbash
のような文字列を出力します。ここではps
、tail
、およびsed
のみを使用しています(GNU範囲を除く、それをチェックするために--posix
を追加してみてください)。それらはすべて標準のPOSIXコマンドです。私はtail
を削除できると確信していますが、私のsed
fuはこれを行うのに十分なほど強力ではありません。
私には、このソリューションはOS Xでは機能しないため、あまり移植性がないと思われます。
シェルとそれに対応するバージョンを見つける方法はたくさんあります。これが私のために働いたいくつかです。
ストレートフォワード
ハッキングなアプローチ
$> *******(一連のランダムな文字を入力すると、出力にシェル名が表示されます。私の場合は -bash:chapter2-a-sample-isomorphic-app:command not found )
下記のコマンドを使用してください。
# ps -p $$ | tail -1 | awk '{print $4}'