bash 如何确定我正在处理的当前 shell
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3327013/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to determine the current shell I'm working on
提问by josh
How can I determine the current shell I am working on?
如何确定我正在处理的当前 shell?
Would the output of the ps
command alone be sufficient?
ps
仅命令的输出就足够了吗?
How can this be done in different flavors of Unix?
如何在不同风格的 Unix 中做到这一点?
回答by DVK
There are three approaches to finding the nameof the current shell's executable:
Please note that all three approaches can be fooled if the executable of the shell is
/bin/sh
, but it's really a renamedbash
, for example (which frequently happens).Thus your second question of whether
ps
output will do is answered with "not always".echo $0
- will print the program name... which in the case of the shell is the actual shell.ps -ef | grep $$ | grep -v grep
- this will look for the current process ID in the list of running processes. Since the current process is the shell, it will be included.This is not 100% reliable, as you might have otherprocesses whose
ps
listing includes the same number as shell's process ID, especially if that ID is a small number (for example, if the shell's PID is "5", you may find processes called "java5" or "perl5" in the samegrep
output!). This is the second problem with the "ps" approach, on top of not being able to rely on the shell name.echo $SHELL
- The path to the current shell is stored as theSHELL
variable for any shell. The caveat for this one is that if you launch a shell explicitly as a subprocess (for example, it's not your login shell), you will get your login shell's value instead. If that's a possibility, use theps
or$0
approach.
If, however, the executable doesn't match your actual shell (e.g.
/bin/sh
is actually bash or ksh), you need heuristics. Here are some environmental variables specific to various shells:$version
is set on tcsh$BASH
is set on bash$shell
(lowercase) is set to actual shell name in csh or tcsh$ZSH_NAME
is set on zshksh has
$PS3
and$PS4
set, whereas the normal Bourne shell (sh
) only has$PS1
and$PS2
set. This generally seems like the hardest to distinguish - the onlydifference in the entire set of environment variables betweensh
andksh
we have installed on Solaris boxen is$ERRNO
,$FCEDIT
,$LINENO
,$PPID
,$PS3
,$PS4
,$RANDOM
,$SECONDS
, and$TMOUT
.
有三种方法可以找到当前 shell 的可执行文件的名称:
请注意,如果 shell 的可执行文件是
/bin/sh
,则所有三种方法都可能被愚弄,但它实际上是一个重命名的bash
,例如(经常发生)。因此,您的第二个问题是否
ps
输出将用“不总是”来回答。echo $0
- 将打印程序名称...在外壳的情况下是实际的外壳。ps -ef | grep $$ | grep -v grep
- 这将在正在运行的进程列表中查找当前进程 ID。由于当前进程是外壳程序,因此它将被包含在内。这不是 100% 可靠的,因为您可能有其他进程的
ps
列表包含与 shell 的进程 ID 相同的数字,特别是如果该 ID 是一个小数字(例如,如果 shell 的 PID 为“5”,您可能会发现进程被称为同一grep
输出中的“java5”或“perl5” !)。这是“ps”方法的第二个问题,除了不能依赖外壳名称。echo $SHELL
- 当前 shell 的路径被存储SHELL
为任何 shell的变量。对此的警告是,如果您将 shell 作为子进程显式启动(例如,它不是您的登录 shell),您将获得登录 shell 的值。如果有可能,请使用ps
or$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
设置。这通常似乎是最难区分的 -和我们在 Solaris boxen 上安装的整个环境变量集的唯一区别是, , , , , , , , 和。sh
ksh
$ERRNO
$FCEDIT
$LINENO
$PPID
$PS3
$PS4
$RANDOM
$SECONDS
$TMOUT
回答by Matthew Slattery
ps -p $$
ps -p $$
should work anywhere that the solutions involving ps -ef
and grep
do (on any Unix variant which supports POSIX options for ps
) and will not suffer from the false positives introduced by grepping for a sequence of digits which may appear elsewhere.
应该在解决方案涉及ps -ef
和grep
执行的任何地方工作(在支持POSIX 选项的ps
任何 Unix 变体上),并且不会受到由 grepping 可能出现在其他地方的数字序列引入的误报。
回答by Nahuel Fouilleul
Try
尝试
ps -p $$ -oargs=
or
或者
ps -p $$ -ocomm=
回答by Peter Lamberg
If you just want to ensure the user is invoking a script with Bash:
如果您只想确保用户使用 Bash 调用脚本:
if [ ! -n "$BASH" ] ;then echo Please run this script ps | grep `echo $$` | awk '{ print }'
with bash; exit 1; fi
回答by karlphillip
You can try:
你可以试试:
echo $SHELL
Or:
或者:
ksh: aaaaa: not found [No such file or directory]
bash: aaaaa: command not found
回答by sr01853
$SHELL
need not always show the current shell. It only reflects the default shell to be invoked.
$SHELL
不必总是显示当前外壳。它仅反映要调用的默认 shell。
To test the above, say bash
is the default shell, try echo $SHELL
, and then in the same terminal, get into some other shell (KornShell(ksh) for example) and try $SHELL
. You will see the result as bash in both cases.
要测试上述内容,假设bash
是默认 shell, try echo $SHELL
,然后在同一个终端中,进入其他 shell(例如KornShell(ksh))并 try $SHELL
。在这两种情况下,您都会看到结果为 bash。
To get the name of the current shell, Use cat /proc/$$/cmdline
. And the path to the shell executable by readlink /proc/$$/exe
.
要获取当前 shell 的名称,请使用cat /proc/$$/cmdline
. 以及 shell 可执行文件的路径readlink /proc/$$/exe
。
回答by ennuikiller
回答by user5659949
I have a simple trick to find the current shell. Just type a random string (which is not a command). It will fail and return a "not found" error, but at start of the line it will say which shell it is:
我有一个简单的技巧来找到当前的 shell。只需键入一个随机字符串(这不是命令)。它会失败并返回“未找到”错误,但在行首它会说明它是哪个 shell:
ls -l /proc/$$/exe | sed 's%.*/%%'
回答by vadimbog
The following will always give the actual shell used - it gets the name of the actual executable and not the shell name (i.e. ksh93
instead of ksh
, etc.). For /bin/sh
, it will show the actual shell used, i.e. dash
.
以下将始终给出实际使用的 shell - 它获取实际可执行文件的名称而不是 shell 名称(即ksh93
代替ksh
等)。对于/bin/sh
,它将显示实际使用的外壳,即dash
.
basename $(readlink /proc/$$/exe)
I know that there are many who say the ls
output should never be processed, but what is the probability you'll have a shell you are using that is named with special characters or placed in a directory named with special characters? If this is still the case, there are plenty of other examples of doing it differently.
我知道有很多人说ls
永远不应该处理输出,但是您使用的外壳以特殊字符命名或放置在以特殊字符命名的目录中的可能性有多大?如果情况仍然如此,那么还有很多其他不同的例子。
As pointed out by Toby Speight, this would be a more proper and cleaner way of achieving the same:
正如Toby Speight所指出的,这将是实现相同目标的更合适和更清洁的方法:
ps -p $$
回答by David Ferenczy Rogo?an
I have tried many different approaches and the best one for me is:
我尝试了许多不同的方法,对我来说最好的方法是:
ps -p $$ | tail -1 | awk '{print $NF}'
It also works under Cygwinand cannot produce false positives as PID grepping. With some cleaning, it outputs just an executable name (under Cygwin with path):
它也可以在Cygwin下工作,并且不会像 PID grepping 那样产生误报。通过一些清理,它只输出一个可执行文件名(在带有路径的 Cygwin 下):
# Print currently active shell
shell () {
ps -p $$ | tail -1 | awk '{print $NF}'
}
You can create a function so you don't have to memorize it:
您可以创建一个函数,这样您就不必记住它:
##代码##...and then just execute shell
.
...然后执行shell
.
It was tested under Debian and Cygwin.
它在 Debian 和 Cygwin 下进行了测试。