我有两个进程foo
和bar
,用管道连接:
$ foo | bar
Run Code Online (Sandbox Code Playgroud)
bar
总是退出 0;我对foo
. 有什么办法可以得到吗?
大多数 shell 提供类似&&
和;
以某种方式链接命令执行的功能。但是如果一个命令已经在运行,我是否仍然可以根据第一个命令的结果以某种方式添加另一个要执行的命令?
说我跑了
$ /bin/myprog
some output...
Run Code Online (Sandbox Code Playgroud)
但我真的很想要/bin/myprog && /usr/bin/mycleanup
。我无法杀死myprog
并重新启动一切,因为会浪费太多时间。我可以Ctrl+Z它和fg
/bg
如果有必要。这是否允许我链接另一个命令?
我最感兴趣的是 bash,但欢迎所有常见 shell 的答案!
当一个进程被一个可处理的信号杀死时,例如SIGINT
orSIGTERM
但它不处理该信号,该进程的退出代码是什么?
对于无法处理的信号,例如SIGKILL
?
据我所知,杀死进程SIGINT
可能会导致退出代码130
,但这会因内核或外壳实现而异吗?
$ cat myScript
#!/bin/bash
sleep 5
$ ./myScript
<ctrl-c here>
$ echo $?
130
Run Code Online (Sandbox Code Playgroud)
我不确定如何测试其他信号...
$ ./myScript &
$ killall myScript
$ echo $?
0 # duh, that's the exit code of killall
$ killall -9 myScript
$ echo $?
0 # same problem
Run Code Online (Sandbox Code Playgroud) 此脚本不回显“之后”:
#!/bin/bash -e
echo "before"
echo "anything" | grep e # it would if I searched for 'y' instead
echo "after"
exit
Run Code Online (Sandbox Code Playgroud)
如果我删除了-e
shebang 行上的选项,它也会如此,但我希望保留它,以便我的脚本在出现错误时停止。我不认为 grep 找不到匹配项是错误。我怎样才能防止它突然退出?
我有一个脚本,当我想要它时它不会退出。
具有相同错误的示例脚本是:
#!/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
如果不是脚本,退出是什么?
我想用失败的命令测试我的脚本。我可以使用带有错误参数的现有命令。我还可以编写一个简单的脚本,该脚本会立即因失败而退出。这两种方法对我来说都很容易做和工作,但是如果有一个用于此目的的标准命令,我想改用它。
我研究 Linux 内核行为已经有一段时间了,我一直很清楚:
当一个进程终止时,它的所有子进程都会返回给该
init
进程(PID 1),直到它们最终终止。
然而,最近,一个比我在内核方面更有经验的人告诉我:
当一个进程退出时,它的所有子进程也会死亡(除非你
NOHUP
在这种情况下使用它们返回到init
)。
现在,即使我不相信这一点,我仍然编写了一个简单的程序来确保它。我知道我不应该依赖时间 ( sleep
) 进行测试,因为它完全取决于进程调度,但对于这个简单的情况,我认为这已经足够了。
int main(void){
printf("Father process spawned (%d).\n", getpid());
sleep(5);
if(fork() == 0){
printf("Child process spawned (%d => %d).\n", getppid(), getpid());
sleep(15);
printf("Child process exiting (%d => %d).\n", getppid(), getpid());
exit(0);
}
sleep(5);
printf(stdout, "Father process exiting (%d).\n", getpid());
return EXIT_SUCCESS;
}
Run Code Online (Sandbox Code Playgroud)
这是程序的输出,ps
每次printf
通话时都有相关的结果:
$ ./test &
Father process spawned (435).
$ ps -ef | grep test
myuser 435 392 tty1 …
Run Code Online (Sandbox Code Playgroud) 考虑这个片段:
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
是为了什么?
我正在尝试编写一个函数来替换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中的好方法是什么?
我对 bash 脚本末尾的退出代码的含义感到困惑:我知道退出代码 0 表示它成功完成,并且还有更多的退出代码编号(如果我没记错的话,是 127?)
我的问题是当在脚本末尾看到退出代码 0 时,它是否会强制退出代码为 0,即使脚本失败还是有其他含义?
exit ×10
shell ×5
bash ×4
shell-script ×4
exit-status ×3
subshell ×3
process ×2
command-line ×1
fork ×1
grep ×1
init ×1
kill ×1
pipe ×1
signals ×1