通过管道连接的 Shell 脚本:捕获一个脚本的终止

通过管道连接的 Shell 脚本:捕获一个脚本的终止

我有两个 shell 脚本,一个在服务器上运行并将一些文件写入临时目录。然后该目录作为 tar 存档发送到 stdout。最后(或者当它被中断时),应该删除临时目录。服务器脚本(例如保存在“~/get_dumps.sh”中)如下所示:

#!/bin/sh
set -e
temp_dir=`mktemp -d`
cd $temp_dir
trap "rm -r $temp_dir; exit" HUP INT TERM PIPE
for db in db1 db2 db3
  do
    pg_dump $db postgres > $db.sql
done
tar cJf - .
rm -r $temp_dir

使用以下脚本从客户端调用服务器脚本:

#!/bin/sh
set -e
temp_dir=`mktemp -d`
trap "rm -r $temp_dir; exit" HUP INT TERM PIPE
mkdir /tmp/dumps
ssh server '~/get_dumps.sh' | tar xJf - -C $temp_dir
ls $temp_dir
rm -r $temp_dir

如果我运行客户端脚本并按 Ctrl-C,则客户端和服务器上的临时目录都不会被删除。为什么trap这里不起作用?

编辑:首先我忘记添加set -e.

答案1

问题是set -e。如果在多个命令通过管道连接在一起时按下 Ctrl-c,SIGINT 不会发送到脚本,而是发送到其他地方。这会产生一个错误,该错误由 处理set -e,因此脚本直接退出。要在带有管道的脚本中使用set -e可靠,还必须捕获EXIT

#!/bin/sh
set -e
temp_dir=`mktemp -d`
cd $temp_dir
trap "rm -r $temp_dir; exit" HUP INT TERM PIPE EXIT
 for db in db1 db2 db3
   do
     pg_dump $db postgres > $db.sql
done
tar cJf - .

在这种情况下,法线也exit由陷阱处理,这在许多情况下无论如何都是有用的。

相关内容