Trap 和 SIGINT 在 bash 中。

huangapple go评论63阅读模式
英文:

Trap and SIGINT in bash

问题

#!/bin/bash

count=0

for i in 'seq 1 5';
do
    trap ctrl_c SIGINT
    ((count=count+1))
done

echo $count

这是您提供的脚本。您希望在用户使用Ctrl+C的次数达到5次时才允许用户退出。然而,脚本中存在一些问题。首先,'seq 1 5' 应该是反引号(`seq 1 5`),以便执行seq 1 5命令。其次,trap 命令需要指定要执行的函数,但在脚本中并没有定义 ctrl_c 函数。以下是修复后的脚本示例:

#!/bin/bash

count=0

# 定义 ctrl_c 函数
ctrl_c() {
    ((count=count+1))
    if [ $count -eq 5 ]; then
        exit 0
    fi
}

for i in `seq 1 5`;
do
    trap ctrl_c SIGINT
done

# 无限循环以等待用户的 Ctrl+C 输入
while true; do
    sleep 1
done

此脚本会在用户第5次按下Ctrl+C时退出。

英文:

I am creating a script, using trap, that will count the number of times a user uses ctrl_c and then allows the user to finally quit on the 5th attempt.

#!/bin/bash

count=0

for i in 'seq 1 5';
do

trap ctrl_c SIGINT
((count=count+1))

done

echo $count

Not sure if I am on the right track for this one. Or if I am using trap with SIGINT correctly. When I run this script I just get 1. I do not get the option to try ^C multiple times.

答案1

得分: 1

我想我明白你不理解trap的问题。以下是使用你的代码的示例。

有一些关于trap如何工作的文章在StackOverflow上,例如:https://stackoverflow.com/questions/14197470/how-does-trap-kill-work-in-bash-on-linux

trap在这里有描述:https://www.gnu.org/savannah-checkouts/gnu/bash/manual/html_node/Bourne-Shell-Builtins.html

在GitHub上也有很多使用它的示例。如果我的示例不够清楚,希望其中一个对你有帮助。https://github.com/search?q=trap+SIGINT+language%3AShell&type=code&ref=advsearch

我认为cleanup的示例最有帮助。

#/bin/bash

ctrl_c() {
  ((count=count+1))
  [[ count == 5 ]] && (
    echo $count
    exit
  )
}

count=0
trap ctrl_c SIGINT
# 做一些事情
英文:

I think I see the issue you are having understanding trap. Below is an example using your code.

There are a few articles about how trap works here on StackOverflow. For example https://stackoverflow.com/questions/14197470/how-does-trap-kill-work-in-bash-on-linux

trap is described here https://www.gnu.org/savannah-checkouts/gnu/bash/manual/html_node/Bourne-Shell-Builtins.html

There are many examples of its use on GitHub too. I hope one of them helps if my example isn't clear. https://github.com/search?q=trap+SIGINT+language%3AShell&type=code&ref=advsearch

I think the cleanup examples are most helpful.

#/bin/bash

ctrl_c() {
  ((count=count+1))
  [[ count == 5 ]] && (
    echo $count
    exit
  )
}

count=0
trap ctrl_c SIGINT
# do stuff

</details>



# 答案2
**得分**: 0

以下是您要翻译的内容:

No, it's `trap [-lp] [[arg] sigspec]` per [man 1 bash](https://www.man7.org/linux/man-pages/man1/bash.1.html)  (or think of it as `trap command_to_run signal[s]`) So can set 2 `trap` instructions to count the &lt;kbd&gt;Ctrl+C&lt;/kbd&gt; `SIGINT` signals and then to print `count` when the program terminates, (1) a `trap` for &lt;kbd&gt;Ctrl+C&lt;/kbd&gt; to catch `SIGINT`and (2) to handle exit or termination (signals `EXIT` and `SIGTERM`) to output `count` at the end.  (see [man 7 signal](https://man7.org/linux/man-pages/man7/signal.7.html) for available signals and corresponding numbers or just type `trap -l` at the command line) 

The `-l` option causes the shell to print a list of the signal names and numbers (try it `trap -l` at the command line) and `-p` options allow you to display the list of commands associated with a `sigspec`. 

You can actually do something like the following where you just loop continually with `read` and a timeout, handing `&#39;q&#39;` to quit and relying on your `SIGINT` `trap` to increment the counter, e.g.

```bash
#!/bin/bash

declare -i count=0    ## may as well declare count as int type

## define 2 trap actions, one for script termination or exit
#  and one to increment count on Ctrl+C
trap &#39;printf &quot;count: %d\n&quot; &quot;$count&quot;&#39; SIGTERM EXIT
trap &#39;count=$((count + 1))&#39; SIGINT

## output simple directions to tell the user what to do
printf &quot;type &#39;q&#39; to quit or Ctrl+C to increment count\n&quot;

while :   ## loop continually
do
  read -r -s -N 1 -t 1 resp;    ## read into resp with 1 sec timeout
  [ &quot;$resp&quot; = q ] &amp;&amp; break      ## if &#39;q&#39; entered, break loop
done

(of course, you can simply output count after you exit the loop, but setting two trap instructions provides an additional way to handle it and demonstrates setting multiple traps)

Example Use/Output

Where we hit <kbd>Ctrl+C</kbd> 5 times before pressing &#39;q&#39;,

$ bash trapcount.sh
type &#39;q&#39; to quit or Ctrl+C to increment count
count: 5

See What Is Happening

You can also write a simple function that is used as the trap action that will indicate <kbd>Ctrl+C</kbd> was pressed and provide the current count. For example:

#!/bin/bash

declare -i count=0      ## may as well declare count as int type

increment_count() {     ## simle function to use as trap action
  count=$((count + 1))  ## incement and output count
  printf &quot;Ctrl+C handled, count: %d\n&quot; &quot;$count&quot;
}

## define 2 trap actions, one for script termination or exit
#  and one to increment count on Ctrl+C
trap &#39;printf &quot;count: %d\n&quot; &quot;$count&quot;&#39; SIGTERM EXIT
trap increment_count SIGINT

## output simple directions to tell the user what to do
printf &quot;type &#39;q&#39; to quit or Ctrl+C to increment count\n&quot;

while :   ## loop continually
do
  read -r -s -N 1 -t 1 resp;    ## read into resp with 1 sec timeout
  [ &quot;$resp&quot; = q ] &amp;&amp; break      ## if &#39;q&#39; entered, break loop
done

Example Use/Output

Same 5 <kbd>Ctrl+C</kbd> before &#39;q&#39;:

$ bash trapcount2.sh
type &#39;q&#39; to quit or Ctrl+C to increment count
Ctrl+C handled, count: 1
Ctrl+C handled, count: 2
Ctrl+C handled, count: 3
Ctrl+C handled, count: 4
Ctrl+C handled, count: 5
count: 5

That provides a bit better feedback.

Let me know if you have questions.

英文:

No, it's trap [-lp] [[arg] sigspec] per man 1 bash (or think of it as trap command_to_run signal

展开收缩
) So can set 2 trap instructions to count the <kbd>Ctrl+C</kbd> SIGINT signals and then to print count when the program terminates, (1) a trap for <kbd>Ctrl+C</kbd> to catch SIGINTand (2) to handle exit or termination (signals EXIT and SIGTERM) to output count at the end. (see man 7 signal for available signals and corresponding numbers or just type trap -l at the command line)

The -l option causes the shell to print a list of the signal names and numbers (try it trap -l at the command line) and -p options allow you to display the list of commands associated with a sigspec.

You can actually do something like the following where you just loop continually with read and a timeout, handing &#39;q&#39; to quit and relying on your SIGINT trap to increment the counter, e.g.

#!/bin/bash

declare -i count=0    ## may as well declare count as int type

## define 2 trap actions, one for script termination or exit
#  and one to increment count on Ctrl+C
trap &#39;printf &quot;count: %d\n&quot; &quot;$count&quot;&#39; SIGTERM EXIT
trap &#39;count=$((count + 1))&#39; SIGINT

## output simple directions to tell the user what to do
printf &quot;type &#39;q&#39; to quit or Ctrl+C to increment count\n&quot;

while :   ## loop continually
do
  read -r -s -N 1 -t 1 resp;    ## read into resp with 1 sec timeout
  [ &quot;$resp&quot; = q ] &amp;&amp; break      ## if &#39;q&#39; entered, break loop
done

(of course, you can simply output count after you exit the loop, but setting two trap instructions provides an additional way to handle it and demonstrates setting multiple traps)

Example Use/Output

Where we hit <kbd>Ctrl+C</kbd> 5 times before pressing &#39;q&#39;,

$ bash trapcount.sh
type &#39;q&#39; to quit or Ctrl+C to increment count
count: 5

See What Is Happening

You can also write a simple function that is used as the trap action that will indicate <kbd>Ctrl+C</kbd> was pressed and provide the current count. For example:

#!/bin/bash

declare -i count=0      ## may as well declare count as int type

increment_count() {     ## simle function to use as trap action
  count=$((count + 1))  ## incement and output count
  printf &quot;Ctrl+C handled, count: %d\n&quot; &quot;$count&quot;
}

## define 2 trap actions, one for script termination or exit
#  and one to increment count on Ctrl+C
trap &#39;printf &quot;count: %d\n&quot; &quot;$count&quot;&#39; SIGTERM EXIT
trap increment_count SIGINT

## output simple directions to tell the user what to do
printf &quot;type &#39;q&#39; to quit or Ctrl+C to increment count\n&quot;

while :   ## loop continually
do
  read -r -s -N 1 -t 1 resp;    ## read into resp with 1 sec timeout
  [ &quot;$resp&quot; = q ] &amp;&amp; break      ## if &#39;q&#39; entered, break loop
done

Example Use/Output

Same 5 <kbd>Ctrl+C</kbd> before &#39;q&#39;:

$ bash trapcount2.sh
type &#39;q&#39; to quit or Ctrl+C to increment count
Ctrl+C handled, count: 1
Ctrl+C handled, count: 2
Ctrl+C handled, count: 3
Ctrl+C handled, count: 4
Ctrl+C handled, count: 5
count: 5

That provides a bit better feedback.

Let me know if you have questions.

huangapple
  • 本文由 发表于 2023年3月12日 12:28:58
  • 转载请务必保留本文链接:https://go.coder-hub.com/75711050.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定