jes*_*e_b 32 shell bash exit subshell
我正在尝试编写一个函数来替换exit内置函数的功能,以防止自己退出终端。
我曾尝试使用SHLVL环境变量,但它在子外壳中似乎没有改变:
$ echo $SHLVL
1
$ ( echo $SHLVL )
1
$ bash -c 'echo $SHLVL'
2
Run Code Online (Sandbox Code Playgroud)
我的功能如下:
exit () {
if [[ $SHLVL -eq 1 ]]; then
printf '%s\n' "Nice try!" >&2
else
command exit
fi
}
Run Code Online (Sandbox Code Playgroud)
不过,这不允许我exit在子外壳中使用:
$ exit
Nice try!
$ (exit)
Nice try!
Run Code Online (Sandbox Code Playgroud)
检测我是否在子shell中的好方法是什么?
der*_*ert 45
在bash中,你可以比较$BASHPID,以$$
$ ( if [ "$$" -eq "$BASHPID" ]; then echo not subshell; else echo subshell; fi )
subshell
$ if [ "$$" -eq "$BASHPID" ]; then echo not subshell; else echo subshell; fi
not subshell
Run Code Online (Sandbox Code Playgroud)
如果您不在 bash 中,$$则应在子 shell 中保持不变,因此您需要通过其他方式获取实际进程 ID。
获取实际 pid 的一种方法是sh -c 'echo $PPID'. 如果你只是把它放在一个普通的地方,( … )它可能看起来不起作用,因为你的 shell 已经优化了 fork。尝试额外的 no-op 命令( : ; sh -c 'echo $PPID'; : ),让它认为 subshell 太复杂而无法优化。这种方法归功于 Stack Overflow上的John1024。
Fre*_*ddy 43
怎么样BASH_SUBSHELL?
BASH_SUBSHELL
当 shell
在该环境中开始执行时,在每个子 shell 或子 shell 环境中递增 1 。初始值为 0。
$ echo $BASH_SUBSHELL
0
$ (echo $BASH_SUBSHELL)
1
Run Code Online (Sandbox Code Playgroud)
mos*_*svy 20
[这应该是一条评论,但我的评论往往会被版主删除,所以这将作为一个答案,即使删除我也可以将其用作参考]
UsingBASH_SUBSHELL是完全不可靠的,因为它只在某些子 shell 中设置为 1 ,而不是在所有子 shell 中。
$ (echo $BASH_SUBSHELL)
1
$ echo $BASH_SUBSHELL | cat
0
Run Code Online (Sandbox Code Playgroud)
声称管道命令,在运行的子进程是不是之前真正实际子shell,考虑这个man bash片断:
管道中的每个命令都作为单独的进程(即,在子外壳中)执行。
以及实际含义 - 脚本片段是否运行在子进程中是必不可少的,而不是一些术语狡辩。
正如在这个问题的答案中已经解释的那样,唯一的解决方案是检查是否$BASHPID等于$$或可移植但效率低得多:
if [ "$(exec sh -c 'echo "$PPID"')" != "$$" ]; then
echo you\'re in a subshell
fi
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
6316 次 |
| 最近记录: |