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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 19:30:16  来源:igfitidea点击:

How to determine the current shell I'm working on

bashunixshellcshtcsh

提问by josh

How can I determine the current shell I am working on?

如何确定我正在处理的当前 shell?

Would the output of the pscommand 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 renamed bash, for example (which frequently happens).

    Thus your second question of whether psoutput will do is answered with "not always".

    1. echo $0- will print the program name... which in the case of the shell is the actual shell.

    2. 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 pslisting 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 same grepoutput!). This is the second problem with the "ps" approach, on top of not being able to rely on the shell name.

    3. echo $SHELL- The path to the current shell is stored as the SHELLvariable 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 the psor $0approach.


  • If, however, the executable doesn't match your actual shell (e.g. /bin/shis actually bash or ksh), you need heuristics. Here are some environmental variables specific to various shells:

    • $versionis set on tcsh

    • $BASHis set on bash

    • $shell(lowercase) is set to actual shell name in csh or tcsh

    • $ZSH_NAMEis set on zsh

    • ksh has $PS3and $PS4set, whereas the normal Bourne shell (sh) only has $PS1and $PS2set. This generally seems like the hardest to distinguish - the onlydifference in the entire set of environment variables between shand kshwe have installed on Solaris boxen is $ERRNO, $FCEDIT, $LINENO, $PPID, $PS3, $PS4, $RANDOM, $SECONDS, and $TMOUT.

  • 有三种方法可以找到当前 shell 的可执行文件的名称

    请注意,如果 shell 的可执行文件是/bin/sh,则所有三种方法都可能被愚弄,但它实际上是一个重命名的bash,例如(经常发生)。

    因此,您的第二个问题是否ps输出将用“不总是”来回答。

    1. echo $0- 将打印程序名称...在外壳的情况下是实际的外壳。

    2. ps -ef | grep $$ | grep -v grep- 这将在正在运行的进程列表中查找当前进程 ID。由于当前进程是外壳程序,因此它将被包含在内。

      这不是 100% 可靠的,因为您可能有其他进程的ps列表包含与 shell 的进程 ID 相同的数字,特别是如果该 ID 是一个小数字(例如,如果 shell 的 PID 为“5”,您可能会发现进程被称为同一grep输出中的“java5”或“perl5” !)。这是“ps”方法的第二个问题,除了不能依赖外壳名称。

    3. echo $SHELL- 当前 shell 的路径被存储SHELL为任何 shell的变量。对此的警告是,如果您将 shell 作为子进程显式启动(例如,它不是您的登录 shell),您将获得登录 shell 的值。如果有可能,请使用psor$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 上安装的整个环境变量集的唯一区别是, , , , , , , , 和。shksh$ERRNO$FCEDIT$LINENO$PPID$PS3$PS4$RANDOM$SECONDS$TMOUT

回答by Matthew Slattery

ps -p $$

ps -p $$

should work anywhere that the solutions involving ps -efand grepdo (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 -efgrep执行的任何地方工作(在支持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

$SHELLneed not always show the current shell. It only reflects the default shell to be invoked.

$SHELL不必总是显示当前外壳。它仅反映要调用的默认 shell。

To test the above, say bashis 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

psis the most reliable method. The SHELL environment variable is not guaranteed to be set and even if it is, it can be easily spoofed.

ps是最可靠的方法。不能保证设置 SHELL 环境变量,即使设置了,也很容易被欺骗。

回答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. ksh93instead 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 lsoutput 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 下进行了测试。