根据我的阅读,将命令放在括号中应该在子shell 中运行它,类似于运行脚本。如果这是真的,如果 x 未导出,它如何查看变量 x?
x=1
Run Code Online (Sandbox Code Playgroud)
(echo $x)在命令行上运行结果为 1
echo $x正如预期的那样,在脚本中运行不会产生任何结果
我理解子shell的语法是(<commands...>),$()只是一个可以从中检索变量值的子shell?
注意:根据文档中的不同措辞,这适用于 bash 4.4。
我有一个脚本,当我想要它时它不会退出。
具有相同错误的示例脚本是:
#!/bin/bash
function bla() {
return 1
}
bla || ( echo '1' ; exit 1 )
echo '2'
Run Code Online (Sandbox Code Playgroud)
我假设会看到输出:
:~$ ./test.sh
1
:~$
Run Code Online (Sandbox Code Playgroud)
但我实际上看到:
:~$ ./test.sh
1
2
:~$
Run Code Online (Sandbox Code Playgroud)
()命令链是否以某种方式创建了一个范围?exit如果不是脚本,退出是什么?
考虑这个片段:
stop () {
echo "${1}" 1>&2
exit 1
}
func () {
if false; then
echo "foo"
else
stop "something went wrong"
fi
}
Run Code Online (Sandbox Code Playgroud)
通常当func被调用时它会导致脚本终止,这是预期的行为。但是,如果它在子shell中执行,例如在
result=`func`
Run Code Online (Sandbox Code Playgroud)
它不会退出脚本。这意味着调用代码每次都必须检查函数的退出状态。有没有办法避免这种情况?这set -e是为了什么?
我有一个关于执行简单命令的简单问题。根据我的理解,当我们ls在交互式 shell 中键入命令时,
如果我的理解是正确的,我们在 shell 提示符下键入的一个简单命令会在子进程上执行,并且该命令的结果不会影响当前 shell 的环境。
如果是这样,那么内置命令cd呢?如果cd在子进程上执行并且不能影响当前shell的环境,那么如何更改当前shell的工作目录?
根据此,将花括号之间的命令列表导致在当前外壳上下文要执行的列表。没有创建子shell。
用ps看到这个在行动
这是直接在命令行上执行的流程管道的流程层次结构。4398 是登录 shell 的 PID:
sleep 2 | ps -H;
PID TTY TIME CMD
4398 pts/23 00:00:00 bash
29696 pts/23 00:00:00 sleep
29697 pts/23 00:00:00 ps
Run Code Online (Sandbox Code Playgroud)
现在遵循直接在命令行上执行的大括号之间的流程管道的流程层次结构。4398 是登录 shell 的 PID。它类似于上面证明所有内容都在当前 shell 上下文中执行的层次结构:
{ sleep 2 | ps -H; }
PID TTY TIME CMD
4398 pts/23 00:00:00 bash
29588 pts/23 00:00:00 sleep
29589 pts/23 00:00:00 ps
Run Code Online (Sandbox Code Playgroud)
现在,这是sleep管道中本身放置在大括号内时的流程层次结构(因此总共有两级大括号)
{ { sleep 2; } | ps -H; }
PID TTY …Run Code Online (Sandbox Code Playgroud) 我正在尝试编写一个函数来替换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中的好方法是什么?
我似乎误解了创建子 shell 的 Bash 规则。我认为括号总是会创建一个子shell,它作为自己的进程运行。
然而,情况似乎并非如此。在代码片段 A(如下)中,第二个sleep命令不在单独的 shell 中运行(由pstree在另一个终端中确定)。但是,在代码片段 B 中,第二个sleep命令确实在单独的 shell中运行。片段之间的唯一区别是第二个片段在括号内有两个命令。
有人可以解释一下何时创建子shell的规则吗?
代码片段 A:
sleep 5
(
sleep 5
)
Run Code Online (Sandbox Code Playgroud)
代码片段 B:
sleep 5
(
x=1
sleep 5
)
Run Code Online (Sandbox Code Playgroud) 假设我们有一个像这样的 bash 脚本:
echo "x" &
echo "y" &
echo "z" &
.....
echo "Z" &
wait
Run Code Online (Sandbox Code Playgroud)
有没有办法收集子外壳/子进程的退出代码?正在寻找方法来做到这一点,但找不到任何东西。我需要并行运行这些子shell,否则会更容易。
我正在寻找一个通用的解决方案(我有一个未知/动态数量的子进程并行运行)。
2013 年 8 月 19 日,Randal L. Schwartz发布了这个shell 脚本,旨在确保在 Linux 上“只有一个 [该] 脚本实例正在运行,没有竞争条件或必须清理锁定文件”:
#!/bin/sh
# randal_l_schwartz_001.sh
(
if ! flock -n -x 0
then
echo "$$ cannot get flock"
exit 0
fi
echo "$$ start"
sleep 10 # for testing. put the real task here
echo "$$ end"
) < $0
Run Code Online (Sandbox Code Playgroud)
它似乎像宣传的那样工作:
$ ./randal_l_schwartz_001.sh & ./randal_l_schwartz_001.sh
[1] 11863
11863 start
11864 cannot get flock
$ 11863 end
[1]+ Done ./randal_l_schwartz_001.sh
$
Run Code Online (Sandbox Code Playgroud)
以下是我的理解:
<其自身内容的副本(即 from …