如何确定我当前所在的交互式 shell(命令行)
如何确定我当前正在使用的 shell?
仅使用 ps
命令的输出就足够了吗?
如何在不同版本的 Unix 中完成此操作?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
如何确定我当前正在使用的 shell?
仅使用 ps
命令的输出就足够了吗?
如何在不同版本的 Unix 中完成此操作?
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
接受
或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
发布评论
评论(29)
我尝试了许多不同的方法,对我来说最好的一种是:
它也适用于 Cygwin 和不能像 PID grepping 那样产生误报。经过一些清理,它只输出一个可执行文件名称(在带有路径的 Cygwin 下):
您可以创建一个函数,这样您就不必记住它:
...然后只需执行
shell
。它在 Debian 和 Cygwin 下进行了测试。
I have tried many different approaches and the best one for me is:
It also works under Cygwin and cannot produce false positives as PID grepping. With some cleaning, it outputs just an executable name (under Cygwin with path):
You can create a function so you don't have to memorize it:
...and then just execute
shell
.It was tested under Debian and Cygwin.
以下内容将始终给出实际使用的 shell - 它获取实际可执行文件的名称,而不是 shell 名称(即
ksh93
而不是ksh
等)。对于/bin/sh
,它将显示实际使用的shell,即dash
。我知道有很多人说 ls 输出永远不应该被处理,但是您正在使用的 shell 以特殊字符命名或放置在名为的目录中的可能性是多少特殊字符?如果情况仍然如此,那么还有很多其他以不同方式进行操作的示例。
正如 Toby Speight 所指出的,这将是实现相同目标的更正确、更简洁的方法:
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 ofksh
, etc.). For/bin/sh
, it will show the actual shell used, i.e.dash
.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.As pointed out by Toby Speight, this would be a more proper and cleaner way of achieving the same:
我关于打印父进程的变体:
当 AWK 可以为您执行不必要的应用程序时,不要运行不必要的应用程序。
My variant on printing the parent process:
Don't run unnecessary applications when AWK can do it for you.
假设您的
/bin/sh
支持 POSIX 标准并且您的系统安装了lsof
命令 - 在这种情况下,可以使用lsof
的替代方法为pid2path
- 您还可以使用(或改编)以下打印脚本完整路径:Provided that your
/bin/sh
supports the POSIX standard and your system has thelsof
command installed - a possible alternative tolsof
could in this case bepid2path
- you can also use (or adapt) the following script that prints full paths:我的解决方案:
这应该可以跨不同平台和 shell 移植。它像其他解决方案一样使用
ps
,但它不依赖sed
或awk
并过滤掉管道和ps< 中的垃圾。 /code> 本身,因此 shell 应该始终是最后一个条目。这样我们就不需要依赖不可移植的 PID 变量或选择正确的行和列。
我已经在 Debian 和 macOS 上使用 Bash 进行了测试,Z shell (
zsh)和 fish (如果不改变专门针对鱼的表达式,因为它使用不同的 PID 变量)。
My solution:
This should be portable across different platforms and shells. It uses
ps
like other solutions, but it doesn't rely onsed
orawk
and filters out junk from piping andps
itself so that the shell should always be the last entry. This way we don't need to rely on non-portable PID variables or picking out the right lines and columns.I've tested on Debian and macOS with Bash, Z shell (
zsh
), and fish (which doesn't work with most of these solutions without changing the expression specifically for fish, because it uses a different PID variable).没有一个答案适用于
fish
shell (它不没有变量$$
或$0
)。这对我有用(在
sh
、bash
、fish
、ksh
、csh
上测试>、true
、tcsh
和zsh
;openSUSE 13.2):此命令输出类似
bash
的字符串。这里我只使用ps
、tail
和sed
(没有 GNU 扩展;尝试添加--posix
检查它)。它们都是标准的 POSIX 命令。我确信tail
可以被删除,但我的sed
fu 还不够强大,无法做到这一点。None of the answers worked with
fish
shell (it doesn't have the variables$$
or$0
).This works for me (tested on
sh
,bash
,fish
,ksh
,csh
,true
,tcsh
, andzsh
; openSUSE 13.2):This command outputs a string like
bash
. Here I'm only usingps
,tail
, andsed
(without GNU extesions; try to add--posix
to check it). They are all standard POSIX commands. I'm suretail
can be removed, but mysed
fu is not strong enough to do this.如果您只想检查是否正在运行 Bash(特定版本),最好的方法是使用 $BASH_VERSINFO 数组变量。作为(只读)数组变量,它不能在环境中设置,
所以你可以确定它来自(如果有的话)来自当前的 shell。
但是,由于 Bash 在作为
sh
调用时具有不同的行为,因此您还需要检查以/bash
结尾的$BASH
环境变量。在我编写的使用带有
-
(不是下划线)的函数名称并依赖于关联数组(在 Bash 4 中添加)的脚本中,我进行了以下健全性检查(带有有用的用户错误消息):可以省略第一种情况下对功能的有些偏执的功能检查,并假设未来的 Bash 版本是兼容的。
If you just want to check that you are running (a particular version of) Bash, the best way to do so is to use the
$BASH_VERSINFO
array variable. As a (read-only) array variable it cannot be set in the environment,so you can be sure it is coming (if at all) from the current shell.
However, since Bash has a different behavior when invoked as
sh
, you do also need to check the$BASH
environment variable ends with/bash
.In a script I wrote that uses function names with
-
(not underscore), and depends on associative arrays (added in Bash 4), I have the following sanity check (with helpful user error message):You could omit the somewhat paranoid functional check for features in the first case, and just assume that future Bash versions would be compatible.
请尝试这个有用的命令。
Please try this helpful command.
来自 你怎么知道你当前的 shell 是什么?。
From How do you know what your current shell is?.
这不是一个非常干净的解决方案,但它可以满足您的需求。
现在您可以使用
$(getshell) --version
。不过,这只适用于类似 KornShell 的 shell (ksh)。
This is not a very clean solution, but it does what you want.
Now you can use
$(getshell) --version
.This works, though, only on KornShell-like shells (ksh).
执行以下操作来了解您的 shell 是否正在使用 Dash/Bash。
ls –la /bin/sh
:如果结果是
/bin/sh -> /bin/bash
==>那么你的 shell 正在使用 Bash。如果结果是
/bin/sh ->/bin/dash
==>;那么你的 shell 正在使用 Dash。如果您想从 Bash 更改为 Dash 或反之亦然,请使用以下代码:
ln -s /bin/bash /bin/sh
(将 shell 更改为 Bash)注意:如果上述命令导致错误提示 /bin/sh 已存在,请删除 /bin/sh 并重试。
Do the following to know whether your shell is using Dash/Bash.
ls –la /bin/sh
:if the result is
/bin/sh -> /bin/bash
==> Then your shell is using Bash.if the result is
/bin/sh ->/bin/dash
==> Then your shell is using Dash.If you want to change from Bash to Dash or vice-versa, use the below code:
ln -s /bin/bash /bin/sh
(change shell to Bash)Note: If the above command results in a error saying, /bin/sh already exists, remove the /bin/sh and try again.
我喜欢 Nahuel Fouilleul 的特别是解决方案,但我必须在 带有内置 Bash shell 的 Ubuntu 18.04 (Bionic Beaver):
没有临时变量
shellPID
,例如:将仅输出
ps
我。也许您并不都使用非交互模式,这会有所不同。I like Nahuel Fouilleul's solution particularly, but I had to run the following variant of it on Ubuntu 18.04 (Bionic Beaver) with the built-in Bash shell:
Without the temporary variable
shellPID
, e.g. the following:Would just output
ps
for me. Maybe you aren't all using non-interactive mode, and that makes a difference.在 Mac OS X(和 FreeBSD)上:
On Mac OS X (and FreeBSD):
不需要从“ps”的输出中 Grepping PID,因为您可以从 /proc 目录结构中读取任何 PID 的相应命令行:
但是,这可能并不比简单更好:
关于运行一个实际上不同的 shell名称表明,一个想法是使用您之前获得的名称从 shell 请求版本:
sh
似乎失败并退出代码 2,而其他人提供了一些有用的东西(但我无法验证所有因为我没有它们):Grepping PID from the output of "ps" is not needed, because you can read the respective command line for any PID from the /proc directory structure:
However, that might not be any better than just simply:
About running an actually different shell than the name indicates, one idea is to request the version from the shell using the name you got previously:
sh
seems to fail with exit code 2 while others give something useful (but I am not able to verify all since I don't have them):一种方法是:
在我看来,这比另一个答案中建议的使用
-o args
或-o comm
更好(这些可能会使用一些符号链接,例如/bin/sh
指向某个特定的 shell,如 Dash 或 < a href="https://en.wikipedia.org/wiki/Bash_%28Unix_shell%29" rel="nofollow noreferrer">Bash)。上面返回了可执行文件的路径,但请注意,由于 /usr-merge,可能需要检查多个路径(例如,
/bin/bash
和 <代码>/usr/bin/bash)。另请注意,上述内容并不完全 POSIX 兼容(POSIX ps 没有
exe
)。One way is:
which is IMO better than using
-o args
or-o comm
as suggested in another answer (these may use, e.g., some symbolic link like when/bin/sh
points to some specific shell as Dash or Bash).The above returns the path of the executable, but beware that due to /usr-merge, one might need to check for multiple paths (e.g.,
/bin/bash
and/usr/bin/bash
).Also note that the above is not fully POSIX-compatible (POSIX ps doesn't have
exe
).使用
$SHELL
环境变量获取它。一个简单的 sed 可以删除路径:输出:
它在 macOS, Ubuntu 和 CentOS。
Get it with the
$SHELL
environment variable. A simple sed could remove the path:Output:
It was tested on macOS, Ubuntu, and CentOS.
请使用以下命令:
Kindly use the below command:
这个在 Red Hat Linux (RHEL)、macOS、BSD 和一些 AIXes:
或者,如果pstree 可用,
This one works well on Red Hat Linux (RHEL), macOS, BSD and some AIXes:
alternatively, the following one should also work if pstree is available,
您可以使用 echo $SHELL|sed "s/\/bin\///g"
You can use
echo $SHELL|sed "s/\/bin\///g"
我想出了这个:
And I came up with this:
可以通过三种方法查找当前 shell 可执行文件的名称:
请注意,如果 shell 的可执行文件是
/bin/sh
,那么所有三种方法都可能被欺骗,但它实际上是一个重命名的bash
(例如)发生)。因此,您关于
ps
输出是否有效的第二个问题的答案是“并不总是”。echo $0
- 将打印程序名称...在 shell 的情况下是实际的 shell。<代码>ps -ef | $$ | grep $$ | grep -v grep - 这将在正在运行的进程列表中查找当前进程 ID。由于当前进程是shell,所以会被包含进来。
这不是 100% 可靠,因为您可能有其他个进程,其
ps
列表中包含与 shell 进程 ID 相同的数字,特别是当该 ID 很小时(例如,如果 shell 的 PID 为“5”,您可能会在同一个grep
输出中找到名为“java5”或“perl5”的进程!)。 这是“ps”方法的第二个问题,除了无法依赖 shell 名称之外。echo $SHELL
- 当前 shell 的路径存储为任何 shell 的SHELL
变量。对此需要注意的是,如果您显式地将 shell 作为子进程启动(例如,它不是您的登录 shell),您将获得登录 shell 的值。如果可能,请使用ps
或$0
方法。<小时>
/bin/sh
实际上是 bash 或 ksh),则您需要启发式方法。以下是一些特定于各种 shell 的环境变量:$version
在 tcsh 上设置$BASH
在 bash 上设置$shell
(小写)设置为 csh 或 tcsh 中的实际 shell 名称$ZSH_NAME
在 zsh 上设置ksh 设置了
$PS3
和$PS4
,而普通的 Bourne shell (sh< /code>) 仅设置了
$PS1
和$PS2
。这通常看起来是最难区分的 - 我们在 Solaris boxen 上安装的sh
和ksh
之间的整套环境变量中唯一的区别是$ERRNO
、$FCEDIT
、$LINENO
、$PPID
、$PS3
、$PS4
、$RANDOM
、$SECONDS
和$TMOUT
。更新:有人在评论中提出了“
ash
”(Almquist Shell)。它似乎有 2001 个变体,包括dash
;因此,为了避免不必要地夸大答案,这里有一个非常有用的页面,列出了大量各种ash
风格以及它们彼此之间的差异,通常与标准 Bournesh
的差异>:https://www.in-ulm.de/~mascheck/various/灰/There are three approaches to finding the name of 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 other processes 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./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 only difference 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
.UPDATE: Someone brought up "
ash
" (Almquist Shell) in comments. There seem to be 2001 variants of it includingdash
; so in the interest of not blowing up the answer unnecessarily, here's a very useful page listing a ton of various flavours ofash
and their differences from each other and often from stanard Bournesh
: https://www.in-ulm.de/~mascheck/various/ash/ps -p $$
应该可以在涉及
ps -ef
和grep
的解决方案执行的任何地方工作(在任何支持ps
的 POSIX 选项),并且不会遭受错误的影响通过 grep 查找可能出现在其他地方的数字序列而引入的正值。ps -p $$
should work anywhere that the solutions involving
ps -ef
andgrep
do (on any Unix variant which supports POSIX options forps
) and will not suffer from the false positives introduced by grepping for a sequence of digits which may appear elsewhere.使用
-p $$
获取有关当前进程 ID 的信息 ($$
) 和-o
控制输出格式。或者
Use
-p $$
to get info on the current process ID ($$
), and-o
to control the output formatting.or
如果您只想确保用户使用 Bash 调用脚本:
或 参考
If you just want to ensure the user is invoking a script with Bash:
or ref
您可以尝试:
或者:
You can try:
Or:
$SHELL
不需要总是显示当前 shell。它仅反映要调用的默认 shell。要测试上述内容,假设
bash
是默认 shell,尝试echo $SHELL
,然后在同一终端中,进入其他 shell (KornShell (ksh))并尝试$SHELL
。在这两种情况下,您都会看到结果为 bash。要获取当前 shell 的名称,请使用
cat /proc/$$/cmdline
。以及readlink /proc/$$/exe
到 shell 可执行文件的路径。$SHELL
need not always show the current shell. It only reflects the default shell to be invoked.To test the above, say
bash
is the default shell, tryecho $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.To get the name of the current shell, Use
cat /proc/$$/cmdline
. And the path to the shell executable byreadlink /proc/$$/exe
.有很多方法可以找到 shell 及其对应的版本。以下是一些对我有用的。
简单
Hackish 方法
$> ****** (输入一组随机字符,在输出中您将获得 shell 名称。在我的例子中 -bash: Chapter2-a-sample-isomorphic-app: command not find)
There are many ways to find out the shell and its corresponding version. Here are few which worked for me.
Straightforward
Hackish approach
$> ******* (Type a set of random characters and in the output you will get the shell name. In my case -bash: chapter2-a-sample-isomorphic-app: command not found)
我有一个简单的技巧来找到当前的 shell。只需键入一个随机字符串(不是命令)。它将失败并返回“未找到”错误,但在行开头它会说明它是哪个 shell:
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:
ps 是最可靠的方法。 SHELL 环境变量不能保证被设置,即使设置了,也很容易被欺骗。
ps is the most reliable method. The SHELL environment variable is not guaranteed to be set and even if it is, it can be easily spoofed.