【问题标题】:How to send control+c from a bash script?如何从 bash 脚本发送 control+c?
【发布时间】:2011-08-12 23:26:22
【问题描述】:

我在 bash 脚本中启动了多个屏幕,然后在每个屏幕中运行 django 的 runserver 命令。我也希望能够以编程方式阻止它们,这需要我将Control+c 发送到runserver。

如何从我的 bash 脚本发送这些击键?

【问题讨论】:

标签: bash gnu-screen


【解决方案1】:

Ctrl+C 发送SIGINT 信号。

kill -INT <pid> 也发送SIGINT 信号:

# Terminates the program (like Ctrl+C)
kill -INT 888
# Force kill
kill -9 888

假设 888 是您的进程 ID。


注意kill 888 发送SIGTERM 信号,略有不同,但也会要求程序停止。所以如果你知道自己在做什么(程序中没有绑定到SIGINT 的处理程序),一个简单的kill 就足够了。

要获取脚本中最后一个命令的 PID,请使用 $!:

# Launch script in background
./my_script.sh &
# Get its PID
PID=$!
# Wait for 2 seconds
sleep 2
# Kill it
kill $PID

【讨论】:

  • 取决于您是否要将命令 ctrl+c 作为输入发送到其他进程。
  • ⚠️ctrl+c 与kill -SIGINT <pid> 不完全相同。前者将INT 信号发送给组,而后者只发送给给定的<pid>。 See this question.
【解决方案2】:

CTRL-C 通常会向进程发送一个 SIGINT 信号,因此您可以简单地执行以下操作:

kill -INT <processID>

从命令行(或脚本),影响具体的processID。

我说“一般”是因为与大多数 UNIX 一样,这几乎是无限可配置的。如果您执行stty -a,您可以看到哪个键序列与intr 信号相关联。这可能是 CTRL-C 但该键序列可能完全映射到其他东西。


以下脚本显示了这一点(尽管使用TERM 而不是INT,因为在我的环境中sleep 不会对INT 做出反应):

#!/usr/bin/env bash

sleep 3600 &
pid=$!
sleep 5

echo ===
echo PID is $pid, before kill:
ps -ef | grep -E "PPID|$pid" | sed 's/^/   /'
echo ===

( kill -TERM $pid ) 2>&1
sleep 5

echo ===
echo PID is $pid, after kill:
ps -ef | grep -E "PPID|$pid" | sed 's/^/   /'
echo ===

它基本上启动了一个小时日志sleep 进程并获取它的进程ID。然后它会在终止进程之前输出相关的进程详细信息。

稍等片刻后,它会检查进程表以查看进程是否已消失。从脚本的输出可以看出,它确实消失了:

===
PID is 28380, before kill:
   UID   PID     PPID    TTY     STIME      COMMAND
   pax   28380   24652   tty42   09:26:49   /bin/sleep
===
./qq.sh: line 12: 28380 Terminated              sleep 3600
===
PID is 28380, after kill:
   UID   PID     PPID    TTY     STIME      COMMAND
===

【讨论】:

  • 如何获取tomcat等特定进程的pid
【解决方案3】:

ctrl+c和kill -INT &lt;pid&gt;不完全一样

要模拟 ctrl+c 我们需要先了解区别。

kill -INT &lt;pid&gt; 会将INT 信号发送到给定进程(与其pid 一起找到)。

ctrl+c 映射到intr 特殊字符,当终端接收到该字符时,应将INT 发送到该终端的前台进程组。您可以通过定位给定&lt;pid&gt; 的组来模拟这一点。可以通过在 kill 命令中的信号之前添加- 来完成。因此你想要的命令是:

kill -INT -<pid>

您可以使用脚本轻松测试它:

#!/usr/bin/env ruby

fork {
    trap(:INT) {
        puts 'signal received in child!'
        exit
    }
    sleep 1_000
}

puts "run `kill -INT -#{Process.pid}` in any other terminal window."
Process.wait

来源:

【讨论】:

    【解决方案4】:

    您可以使用以下命令获取特定进程(如 MySQL)的 PI​​D: ps -e | pgrep mysql

    此命令将为您提供 MySQL 进程的 PID。例如,13954 现在,在终端上键入以下命令。 杀死-9 13954 这将杀死 MySQL 的进程。

    【讨论】:

      【解决方案5】:
          pgrep -f process_name > any_file_name
          sed -i 's/^/kill /' any_file_name
          chmod 777 any_file_name
          ./any_file_name
      

      例如,'pgrep -f firefox' 将 grep 运行 'firefox' 的 PID 并将这个 PID 保存到一个名为 'any_file_name' 的文件中。 'sed' 命令将在 'any_file_name' 文件中的 PID 号的开头添加 'kill'。第三行将使“any_file_name”文件可执行。现在第四行将终止文件“any_file_name”中可用的 PID。将上述四行写入一个文件并执行该文件可以执行 control-C。对我来说工作得很好。

      【讨论】:

        猜你喜欢
        • 2014-07-27
        • 2010-11-01
        • 2016-07-03
        • 2010-12-21
        • 1970-01-01
        • 1970-01-01
        • 2016-08-12
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多