我有以下简单的 shell 脚本,其中我尝试将 STDERR 和 STDOUT 发送到两个屏幕并将其记录在文件(test.log)中。另外,在退出时,我尝试使用适当的退出代码退出。
在此代码中,我希望它回显第一条消息(在块内)并退出。但是,它会回显这两个语句,并且总是以 0 退出。
$ cat test.sh
#!/bin/ksh
n_exitstatus=0
{
n_exitstatus=1
echo "Inside block : $n_exitstatus"
exit $n_exitstatus
} 2>&1 | tee -a test.log
echo "Before last exit : $n_exitstatus"
exit $n_exitstatus
$ sh test.sh
Inside block : 1
Before last exit : 0
$ echo $?
0
如何修改此脚本以在回显第一条语句后立即退出(要记录在屏幕和文件中)?
答案1
您可以在管道中使用内部代码块。这会强制 shell 运行子 shell。 Exit 只留下该函数。如果拆下管道,| tee -a test.log
它应该按您的预期工作。
因此,最简单的解决方案是从块中删除管道并将其放在内部 echo 命令后面。
您还可以使用该块作为主体创建一个函数,执行它并使用返回值来决定退出,然后再进一步执行外部代码。
编辑 这是一个有用的链接:http://www.bolthole.com/solaris/ksh-functions.html
答案2
这与这个问题密切相关:有没有办法编写一个 bash 函数,无论如何调用它都会中止整个执行?
实施给出的解决方案接受的答案,我们有这个:
$ cat test.ksh
#!/bin/ksh
trap 'exit $n_exitstatus' TERM
SCRIPT_PID="$$"
n_exitstatus=0
{
n_exitstatus=1
echo "Inside block: $n_exitstatus"
kill -s TERM $SCRIPT_PID
} 2>&1 | tee -a test.log
echo "Before last exit: $n_exitstatus"
exit $n_exitstatus
$ chmod +x test.ksh
$ ./test.ksh
Inside block: 1
$ cat test.log
Inside block: 1
唯一不太正确的是脚本的退出状态是 0,而不是 1。这是因为退出发生在外部范围,其中$n_exitstatus
0。