4

我对 bash 脚本还是很陌生,我很难弄清楚为什么这个简单的陷阱没有按预期工作。

目标- 创建一个可以通过按CTRL+跳过的可选等待期C

CTRL+C - 的预期结果立即回显“没有时间打盹!” 并退出。

CTRL+C - 的实际结果立即回显“小睡时间结束”。并退出。

#!/bin/bash

nonap() {
    echo "No time for napping!"
    exit
}

trap nonap INT

echo "Sleeping for 5 seconds, hit ctrl-c to proceed now."
sleep 5 
echo "Naptime over."

为什么我的陷阱函数没有被调用?

4

1 回答 1

4

我刚刚尝试过(在带有 bash 3.2.25 的古老 RHEL Linux 上)并将您的代码保存在trap.sh、运行bash trap.sh并得到:

 Sleeping for 5 seconds, hit ctrl-c to proceed now.

其次是:

No time for napping!

当我打断时,正如你所料。当我让它运行而不中断时,我得到了预期的消息:

Naptime over.

然后你评论道:

至少我知道它应该按预期工作。我正在使用最新版本的 Tinycore Linux 和 GNU bash,版本 4.0.33(1)-release (i686-pc-linux-gnu)。打开一个新终端后,declare -f nonap两者trap都没有返回任何输出。运行此脚本并获得“午睡时间结束”后。输出,trap返回trap -- 'nonap' SIGINTdeclare -f nonap返回我的脚本中定义的函数。

我对此作出回应:

那你是如何运行这个脚本的呢?使用source还是.阅读?是啊; 你一定是。我刚试过,采购时的中断给了我Naptime over.;输入另一个中断虽然给了我No time for napping!并且shell退出了。第二次表现如预期;我不确定在打点脚本时中断是怎么回事。那是意想不到的行为。

你为什么要采购或点这个?为什么不将它用作普通的旧脚本?

没有理由来源......我只是在测试时使用它来运行它。我想我在使用 . 以前,但我还是个新手。我看到的结果与您相同,如果我使用 bash 运行它,它会在第一次中断时按预期工作。

嗯,下面的建议有一个“医生,医生,我的头撞到墙上很痛”的部分,但也有基本的实用主义。

您使用source(在 C shell 或中bash)或.(在 Bourne、Korn、POSIX shell 或bash中)让脚本影响调用 shell 的环境,而不是作为子 shell 运行。解决问题(尽管主要靠侥幸)的好处是当您报告运行脚本后,您已经定义了函数;除非您使用source. 在这种情况下,很明显您不希望trap调用 shell 中的集合。当我运行它时(从kshwith prompt Toru JL:),我得到:

Toru JL: bash
bash-3.2$ trap
bash-3.2$ source trap.sh
Sleeping for 5 seconds, hit ctrl-c to proceed now.

Naptime over.
bash-3.2$ trap
trap -- 'nonap' INT
bash-3.2$ No time for napping!
Toru JL: 

“没时间打盹!” 当我再次按下中断键时出现消息,它终止了bash我要运行的。如果您继续将它与 一起使用source,您可能希望添加trap INT到脚本的末尾,并且您可能还想取消定义该函数。

但是,我认为最好将其全部隔离在一个外壳中并将其作为子进程运行。

但是......你发现当脚本来源时这种东西会玩有趣的游戏很有趣。这是 的行为中的一个小异常bash。我不确定它会上升到“错误”的水平;在声称“错误”之前,我必须相当仔细地阅读大量手册(可能多次)并咨询其他知识渊博的人。

我不确定这是否会带来任何安慰,但我尝试ksh了你的脚本,.它的工作方式符合我们的预期:

Toru JL: ksh
$ . trap.sh
Sleeping for 5 seconds, hit ctrl-c to proceed now.
No time for napping!
Toru JL: 
于 2012-05-17T06:03:10.687 回答