【问题标题】:Clean exit from bashscript which uses read and trap从使用读取和陷阱的 bash 脚本中清除退出
【发布时间】:2014-07-07 13:26:53
【问题描述】:

运行以下脚本
按 Ctrl+C
观察当前终端行为。
按回车几次,尝试执行一些命令。

#!/bin/bash
LOCK_FILE=/tmp/lockfile
clean_up(){
  # Perform program exit housekeeping
  echo -e "Signal Trapped, exiting..."
  # Do some Special operation
  rm -f $LOCK_FILE
  #
  exit 1
}

touch LOCK_FILE
trap clean_up SIGHUP SIGINT SIGTERM
read -s -p "Password: " var
echo -e "\n  Input Password is: $var\n"

我想知道我做错了什么?
我试着做一个干净的出口。 它正在工作,但在退出终端 STDIN 消失后。

【问题讨论】:

  • 你还没有说你期望它做什么或它在你的机器上做什么。
  • @l0b0 实际上,我已经对其进行了测试,这很奇怪。在捕获 SIGINT 时,它会退出程序并弄乱您的外壳(编写命令时没有字符出现,按下回车键时没有换行符)。当您键入 reset 时,此问题已修复。不过,我不知道他的剧本为什么会这样做
  • LOCK_FILE 未分配,一方面...
  • 你好,现在请验证,我已经修改了一点。

标签: bash shell terminal signals bash-trap


【解决方案1】:

read -s 禁用本地回显(根据文档),如果您在读取时ctrl-c 无法重置本地回显的终端模式。比较中断读取之前和之后来自stty -a 的输出,以查看它所做的更改(查看echo* 模式)。

您可以使用reset(根据 Plutox 的评论)或手动重新启用本地回显模式以“修复”问题。

$ stty -a
speed 38400 baud; rows 46; columns 80; line = 0;
intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^D; eol = <undef>;
eol2 = <undef>; swtch = <undef>; start = ^Q; stop = ^S; susp = ^Z; rprnt = ^R;
werase = ^W; lnext = ^V; flush = ^O; min = 1; time = 0;
-parenb -parodd cs8 -hupcl -cstopb cread -clocal -crtscts -cdtrdsr
-ignbrk brkint ignpar -parmrk -inpck -istrip -inlcr -igncr icrnl ixon -ixoff
-iuclc -ixany imaxbel -iutf8
opost -olcuc -ocrnl onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0
isig icanon iexten echo echoe echok -echonl -noflsh -xcase -tostop -echoprt
echoctl echoke
$
$ cat t.sh
#!/bin/bash
clean_up(){
  # Perform program exit housekeeping
  echo -e "Signal Trapped, exiting..."
  # Do some Special operation
  rm -f $LOCK_FILE
  #
  exit 1
}

trap clean_up SIGHUP SIGINT SIGTERM
read -s -p "Password: " var
echo -e "\n  Input Password is: $var\n"
$
$ sh t.sh
Password: Signal Trapped, exiting...
# I ran `stty -a` here but the lack of local echo means it didn't show up.
$ speed 38400 baud; rows 46; columns 80; line = 0;
intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^D; eol = <undef>;
eol2 = <undef>; swtch = <undef>; start = ^Q; stop = ^S; susp = ^Z; rprnt = ^R;
werase = ^W; lnext = ^V; flush = ^O; min = 1; time = 0;
-parenb -parodd cs8 -hupcl -cstopb cread -clocal -crtscts -cdtrdsr
-ignbrk brkint ignpar -parmrk -inpck -istrip -inlcr -igncr icrnl ixon -ixoff
-iuclc -ixany imaxbel -iutf8
opost -olcuc -ocrnl onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0
isig icanon iexten -echo echoe -echok -echonl -noflsh -xcase -tostop -echoprt
echoctl echoke

【讨论】:

  • +1。我正要自己写一个答案:) 如果你不想显示stty -a 的(真正)详细输出,只需在clean_up() 函数中的exit 1 之前添加stty -a &gt; /dev/null 即可
  • @Ploutox stty -a 不会更改设置,只是显示它们。将其添加到 clean_up 函数不会解决问题。添加reset 会但也会产生其他副作用。使用stty echo echok 手动重新启用echoechok 设置将解决问题。
  • 你试过了吗?在函数中使用它对我来说很好
  • @Ploutox 我没有,因为我知道我不需要,但只是为了确保我现在尝试了,不,它没有任何帮助。如果您用ctrl-c 中断read -s,则不会重置模式并且需要执行某些操作(而stty -a 不会这样做)。
  • @Ploutox 我也是,它没有帮助。我记得一种方法,例如将您的终端行为保存在变量中并在陷阱信号中恢复。但是想不起来。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-05-11
  • 1970-01-01
  • 2020-06-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-06-07
相关资源
最近更新 更多