我有一个命令,每次它终止时我都想自动再次运行,所以我运行了这样的命令:
while [ 1 ]; do COMMAND; done;
Run Code Online (Sandbox Code Playgroud)
但如果我不能停止循环,Ctrl-c因为那只会杀死COMMAND而不是整个循环。
我将如何实现类似的功能,但无需关闭终端即可停止?
我有一个shell脚本,多数民众赞成从标准输入读取。在极少数情况下,没有人准备好提供输入,脚本必须超时。在超时的情况下,脚本必须执行一些清理代码。这样做的最佳方法是什么?
这个脚本必须非常便携,包括到 20 世纪没有 C 编译器的 unix 系统和运行 busybox 的嵌入式设备,所以不能依赖 Perl、bash、任何编译语言,甚至完整的 POSIX.2。特别是$PPID,read -t完全符合POSIX标准的和陷阱不可用。写入临时文件也不包括在内;即使所有文件系统都以只读方式安装,脚本也可能运行。
只是为了让事情变得更困难,我还希望脚本在没有超时时能够相当快。特别是我也在Windows(主要是Cygwin)中使用了脚本,其中fork和exec特别低,所以我想尽量减少它们的使用。
简而言之,我有
trap cleanup 1 2 3 15
foo=`cat`
Run Code Online (Sandbox Code Playgroud)
我想添加一个超时。我不能cat用read内置替换。在超时的情况下,我想执行该cleanup功能。
背景:该脚本通过打印一些 8 位字符并比较前后光标位置来猜测终端的编码。脚本的开头测试 stdout 连接到支持的终端,但有时环境是谎言(例如,即使使用 调用它也会plink设置TERM=xtermTERM=dumb)。脚本的相关部分如下所示:
text='Éé' # UTF-8; shows up as Ãé on a latin1 terminal
csi='?['; dsr_cpr="${csi}6n"; dsr_ok="${csi}5n" # ? is an escape character
stty_save=`stty -g`
cleanup () { …Run Code Online (Sandbox Code Playgroud) 我编写了一个带有循环的简单 bash 脚本,用于打印日期和 ping 到远程机器:
#!/bin/bash
while true; do
# *** DATE: Thu Sep 17 10:17:50 CEST 2015 ***
echo -e "\n*** DATE:" `date` " ***";
echo "********************************************"
ping -c5 $1;
done
Run Code Online (Sandbox Code Playgroud)
当我从终端运行它时,我无法使用Ctrl+C. 它似乎将 发送^C到终端,但脚本并没有停止。
MacAir:~ tomas$ ping-tester.bash www.google.com
*** DATE: Thu Sep 17 23:58:42 CEST 2015 ***
********************************************
PING www.google.com (216.58.211.228): 56 data bytes
64 bytes from 216.58.211.228: icmp_seq=0 ttl=55 time=39.195 ms
64 bytes from 216.58.211.228: icmp_seq=1 ttl=55 time=37.759 ms
^C <= That is Ctrl+C …Run Code Online (Sandbox Code Playgroud) 当我过去killall -9 name杀死一个程序时,状态变成僵尸。几分钟后,它真的停止了。那么,在那几分钟里发生了什么?
除了最暴力的kill -9(SIGKILL),我不太明白其他 3 个常见信号(此处)-HUP(1)、-INT(2)和-TERM(15)之间的区别。
在哪些情况下,一种有效而另一种无效?
一般什么时候-9( -KILL) 失败?
对我来说,他们似乎要求进程优雅地终止,而不保存. 评价严酷程度,我会放-HUP < -TERM < -INT < -KILL。
我对用于描述 Linux 信号传递的术语感到困惑。大多数文本都会说“信号被传递到进程”或“信号被传递到线程”。
据我了解,当内核调用该处理程序时,信号被“传递”到驻留在进程中的信号处理程序。该进程本身是异步运行的,这个“交付”过程类似于 CPU 调用中断处理程序。中断处理程序(信号处理程序)不是进程线程,也不是该进程下运行的任何线程,对吗?它是由内核启动的一个单独的线程。
因此,信号不会传递给线程或进程,而是传递给驻留在进程中的信号处理程序,并且不一定与任何特定线程关联。如果这不正确,请告诉我,例如,信号处理程序和 pthread 之间的关联,它证明了“信号传递到 pthread”这一术语的合理性。
我经常开始读取一个大文件,然后在一段时间后想退出,但是从按
Ctrl+C到程序停止有延迟。是否有可能通过多次按Ctrl+C键来缩短延迟?还是我在浪费我的按键?
在一般情况下,终止进程,我们产生这样的信号SIGKILL,SIGTSTP等等。
但是如何知道谁订购了该特定信号,谁将其发送到特定进程,以及信号通常如何执行其操作?信号在内部如何工作?
我想知道 UNIX 信号的安全性。
SIGKILL会杀死进程。那么,当非 root 用户的进程向 root 用户的进程发送信号时会发生什么?进程是否仍然执行信号处理程序?
我遵循公认的答案(gollum 的),然后输入man capabilites,然后我找到了很多关于 Linux 内核的信息。来自man capabilities:
NAME
capabilities - overview of Linux capabilities
DESCRIPTION
For the purpose of performing permission checks, traditional UNIX
implementations distinguish two categories of processes: privileged
processes (whose effective user ID is 0, referred to as superuser or
root), and unprivileged processes (whose effective UID is nonzero).
Privileged processes bypass all kernel permission checks, while
unprivileged processes are subject to full permission checking …Run Code Online (Sandbox Code Playgroud) 从阅读read()和write()调用上的手册页来看,这些调用似乎会被信号中断,无论它们是否必须阻塞。
特别地,假设
O_NONBLOCK 没有设置(即在阻塞模式下运行)read()系统调用以从设备读取,结果在内核空间中执行内核控制路径。read()在内核空间中执行时,先前为其安装处理程序的信号被传递到该进程并调用其信号处理程序。阅读SUSv3 'System Interfaces volume (XSH)' 中的手册页和相应部分,您会发现:
一世。如果 aread()在读取任何数据之前被信号中断(即它必须阻塞,因为没有数据可用),它返回 -1 并errno设置为 [EINTR]。
ii. 如果 aread()在成功读取一些数据后被信号中断(即可以立即开始服务请求),它返回读取的字节数。
问题 A):
我是否正确地假设在任何一种情况下(阻止/不阻止)信号的传递和处理对read()?
案例一。似乎可以理解,因为阻塞read()通常会将进程置于TASK_INTERRUPTIBLE状态,以便在传递信号时,内核将进程置于TASK_RUNNING状态。
但是,当read()不需要阻塞(情况 ii.)并且正在内核空间中处理请求时,我会认为信号的到达及其处理将是透明的,就像硬件的到达和正确处理一样中断会。特别是我会假设,在传递信号时,进程将被临时置于用户模式以执行其信号处理程序,它最终将从该处理程序返回以完成处理中断的read()(在内核空间中),以便read()运行其过程完成之后,进程返回到调用read()(在用户空间中)之后的点,结果读取所有可用字节。
但是二。似乎暗示read()被中断,因为数据立即可用,但它返回仅返回部分数据(而不是全部)。
这让我想到了我的第二个(也是最后一个)问题:
问题 B):
如果我在 A) 下的假设是正确的,为什么会read()被中断,即使它不需要阻塞,因为有数据可以立即满足请求?换句话说,为什么read()在执行信号处理程序后没有恢复,最终导致所有可用数据(毕竟可用)被返回?