DVK*_*DVK 742
有3种方法可以找到当前shell的可执行文件的名称:
请注意,如果shell的可执行文件是,/bin/sh但它实际上是重命名的bash(经常发生),所有3种方法都可能被欺骗.
因此,关于ps输出是否会做的第二个问题是" 并非总是 ".
echo $0 - 将打印程序名称...在shell的情况下是实际的shell
ps -ef | grep $$ | grep -v grep - 这将在正在运行的进程列表中查找当前进程ID.由于当前进程是shell,因此将包含它.
这不是100%可靠,因为您可能有其他进程,其ps列表包含与shell的进程ID相同的编号,特别是如果该ID是一个小#(例如,如果shell的PID为"5",您可能会发现名为"java5"的进程或"perl5"在同一grep输出!).这是"ps"方法的第二个问题,除了不能依赖shell名称.
echo $SHELL- 当前shell的路径存储SHELL为任何shell 的变量.这个问题的警告是,如果你明确地将shell作为子进程启动(例如它不是你的登录shell),你将获得你的登录shell的值.如果可能,请使用ps或$0方法.
但是,如果可执行文件与您的实际shell不匹配(例如/bin/sh实际上是bash或ksh),则需要启发式方法.以下是一些特定于各种shell的环境变量:
$version 在tcsh上设置
$BASH 在bash上设置
$shell (小写)设置为csh或tcsh中的实际shell名称
$ZSH_NAME 在zsh上设置
ksh有$PS3和$PS4设置,而普通的Bourne shell(sh)只有$PS1和$PS2设置.这通常似乎是最难区分-在整组伴有环境之间的变量的唯一的区别sh和ksh我们已经安装在Solaris上Boxen有是$ERRNO,$FCEDIT,$LINENO,$PPID,$PS3,$PS4,$RANDOM,$SECONDS,$TMOUT.
Mat*_*ery 90
ps -p $$
应该在解决方案涉及ps -ef和grep执行的任何地方工作(在任何支持POSIX选项的ps Unix变体上),并且不会遭受grepping为可能出现在其他地方的数字序列引入的误报.
Nah*_*eul 38
尝试
ps -p $$ -oargs=
Run Code Online (Sandbox Code Playgroud)
要么
ps -p $$ -ocomm=
Run Code Online (Sandbox Code Playgroud)
Pet*_*erg 29
如果您只是想确保用户使用bash调用脚本:
if [ ! -n "$BASH" ] ;then echo Please run this script $0 with bash; exit 1; fi
Run Code Online (Sandbox Code Playgroud)
kar*_*lip 19
你可以试试:
ps | grep `echo $$` | awk '{ print $4 }'
Run Code Online (Sandbox Code Playgroud)
要么:
echo $SHELL
Run Code Online (Sandbox Code Playgroud)
sr0*_*853 11
$SHELL不必总是显示当前的shell.它仅反映要调用的默认shell.
为了测试上面的内容,Say bash是默认shell,尝试echo $SHELL,然后在同一个终端中,进入其他shell(例如ksh)并尝试$SHELL,在两种情况下你都会看到结果为bash.
要获取当前shell的名称,请使用cat /proc/$$/cmdline和执行shell可执行文件的路径readlink /proc/$$/exe
ps是最可靠的方法.SHELL envar不保证设置,即使它是,它可以很容易欺骗
小智 8
我有一个简单的技巧来找到当前的shell.只需键入随机字符串(不是命令).它会失败并返回一个"未找到"的错误,但是在行的开头它将说明它是哪个shell:
ksh: aaaaa: not found [No such file or directory]
bash: aaaaa: command not found
Run Code Online (Sandbox Code Playgroud)
这将始终给出实际使用的shell - 获取实际可执行文件的名称而不是shell名称(即ksh93代替ksh等等)For For /bin/sh将显示使用的实际shell:iedash
ls -l /proc/$$/exe | sed 's%.*/%%'
Run Code Online (Sandbox Code Playgroud)
我知道有很多人说ls输出应该是新处理的,但是你有一个使用特殊字符命名的shell或放在一个用特殊字符命名的目录中的概率是多少?如果仍然是这种情况,这里还有很多其他的例子.
有很多方法可以找出shell及其对应的版本。这里有几个对我有用。
直截了当
黑客方法
$> ******* (输入一组随机字符,在输出中你会得到 shell 名称。在我的例子中-bash:chapter2-a-sample-isomorphic-app: command not found)
小智 5
如果您/bin/sh支持 POSIX 标准并且您的系统安装了该命令 -在这种情况下lsof可能的替代方案是- 您还可以使用(或改编)以下打印完整路径的脚本:lsofpid2path
#!/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}'
Run Code Online (Sandbox Code Playgroud)
我尝试了许多不同的方法,对我来说最好的方法是:
ps -p $$
它也可以在Cygwin下工作,并且不能作为PID grepping产生误报。经过一些清理,它仅输出一个可执行文件名称(在Cygwin下带有路径):
ps -p $$ | tail -1 | awk '{print $NF}'
Run Code Online (Sandbox Code Playgroud)
您可以创建一个函数,这样就不必记住它:
# print currently active shell
shell () {
ps -p $$ | tail -1 | awk '{print $NF}'
}
Run Code Online (Sandbox Code Playgroud)
...然后执行shell。
经过Debian和Cygwin的测试。
小智 5
我在打印父进程时的变体:
ps -p $$ | awk '$1 == PP {print $4}' PP=$$
Run Code Online (Sandbox Code Playgroud)
当 AWK 可以为您完成时,不要运行不必要的应用程序。
小智 5
我的解决方案:
ps -o command | grep -v -e "\<ps\>" -e grep -e tail | tail -1
Run Code Online (Sandbox Code Playgroud)
这应该可以跨不同平台和 shell 移植。它像其他解决方案一样使用ps,但它不依赖于sedorawk并过滤掉管道及其ps自身中的垃圾,因此 shell 应该始终是最后一个入口。这样我们就不需要依赖不可移植的 PID 变量或选择正确的行和列。
我已经在 Debian 和 macOS 上使用 Bash、Z shell ( zsh) 和Fish进行了测试(如果不更改专门针对 Fish 的表达式,这些解决方案不适用于大多数解决方案,因为它使用不同的 PID 变量)。