【发布时间】:2011-08-12 23:26:22
【问题描述】:
我在 bash 脚本中启动了多个屏幕,然后在每个屏幕中运行 django 的 runserver 命令。我也希望能够以编程方式阻止它们,这需要我将Control+c 发送到runserver。
如何从我的 bash 脚本发送这些击键?
【问题讨论】:
标签: bash gnu-screen
我在 bash 脚本中启动了多个屏幕,然后在每个屏幕中运行 django 的 runserver 命令。我也希望能够以编程方式阻止它们,这需要我将Control+c 发送到runserver。
如何从我的 bash 脚本发送这些击键?
【问题讨论】:
标签: bash gnu-screen
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 与kill -SIGINT <pid> 不完全相同。前者将INT 信号发送给组,而后者只发送给给定的<pid>。 See this question.
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
===
【讨论】:
pid
kill -INT <pid>不完全一样要模拟 ctrl+c 我们需要先了解区别。
kill -INT <pid> 会将INT 信号发送到给定进程(与其pid 一起找到)。
ctrl+c 映射到intr 特殊字符,当终端接收到该字符时,应将INT 发送到该终端的前台进程组。您可以通过定位给定<pid> 的组来模拟这一点。可以通过在 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
来源:
【讨论】:
您可以使用以下命令获取特定进程(如 MySQL)的 PID: ps -e | pgrep mysql
此命令将为您提供 MySQL 进程的 PID。例如,13954 现在,在终端上键入以下命令。 杀死-9 13954 这将杀死 MySQL 的进程。
【讨论】:
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。对我来说工作得很好。
【讨论】: