简体   繁体   English

如何立即将信号捕获到交互式 Bash shell?

[英]How to immediately trap a signal to an interactive Bash shell?

I try to send a signal from one terminal A to another terminal B. Both run an interactive shell<\/strong> .我尝试从一个终端 A 向另一个终端 B 发送信号。两者都运行一个交互式 shell<\/strong> 。

In terminal B, I trap signal SIGUSR1 like so :在终端 B,我像这样捕获信号 SIGUSR1:

$ trap 'source ~/mycommand' SIGUSR1

The shell may simply be stuck in a blocking read, waiting for command-line input. 外壳程序可能只是停留在阻塞读取中,等待命令行输入。 Hitting enter causes the handler to execute before the entered command. 按下Enter键会使处理程序在输入的命令之前执行。 Running a non-blocking command like wait : 运行非阻塞命令,如wait

$ sleep 60 & wait

then sending the signal causes wait to terminate immediately, followed by the output of the handler. 然后发送信号导致wait立即终止,随后是处理程序的输出。

Based on the answers and my numerous attempt to solve this, I don't think it's possible to catch a trap signal immediately in an interactive bash terminal. 基于答案和我为解决这个问题的无数尝试,我认为不可能在交互式bash终端中立即捕获陷阱信号。

For it to trigger, there must be an interaction from the user. 为了触发它,用户必须进行交互。

This is due to the readline program blocks until a newline is entered. 这是由于readline程序块直到输入换行符所致。 And there is no way to stop this read. 而且没有办法停止读取。

My solution is to use dtach , a small program that emulate the detach feature of screen. 我的解决方案是使用dtach ,这是一个模拟屏幕分离功能的小程序。

This program can run a fully interactive shell and features in its last version a way to communicate via a custom socket to this shell (or whatever program you launch) 该程序可以运行一个完全交互式的外壳程序,并在其最新版本中具有某些功能,可以通过自定义套接字与该外壳程序(或您启动的任何程序)进行通信

To start a new dtach session running an interactive bash, in terminal B : 要在终端B中启动一个新的运行交互式bash的dtach会话,请执行以下操作:

$ dtach -a /tmp/MySocket bash -i

Now from terminal A, we can send a message to the bash session in terminal B like so : 现在从终端A,我们可以像这样向终端B中的bash会话发送消息:

$ echo 'echo hello' | dtach -p /tmp/MySocket

In terminal B, we now see : 在终端B中,我们现在看到:

$ echo hello
hello

To expand on that if I now do in terminal A : 如果我现在在终端A中进行扩展:

$ trap 'echo "cd $(pwd)" | $ trap'echo“ cd $(pwd)” | dtach -p /tmp/MySocket' DEBUG dtach -p / tmp / MySocket'调试

I'll have the directory of the two terminals synced 我将两个终端的目录同步

PS :I'd still like to know if there is a way to do this in pure bash PS:我仍然想知道是否有一种方法可以做到纯正bash

It may be buffering. 它可能正在缓冲。

As a test, try installing a loop trigger. 作为测试,请尝试安装循环触发器。 In window A: 在窗口A中:

{ trap 'ls' USR1; while sleep 1; do echo>/dev/null;done } &
[1] 7316

in window B: 在窗口B中:

 kill -usr1 7316

back in window A the ls is firing when the loop does an echo. 返回到窗口A中,循环执行回显时, ls触发。 Don't know if that will help, but it's something. 不知道这是否会有所帮助,但这是有的。

I use a similar trap so that periodically I can (from a separate cron job) force all idle bash processes to do a 'history -a'.我使用了一个类似的陷阱,以便我可以定期(从一个单独的 cron 作业)强制所有空闲的 bash 进程执行“历史 -a”。 I found that if I trap SIGALRM instead of SIGUSR1, then the bash blocking read seems not to be a problem: the trap runs now, rather than next time one hits return.我发现如果我捕获 SIGALRM 而不是 SIGUSR1,那么 bash 阻塞读取似乎不是问题:陷阱现在运行,而不是下一次点击返回。 I tried SIGINT, but that caused an annoying "^C", followed by a new prompt line, to be displayed.我尝试了 SIGINT,但这会导致显示一个烦人的“^C”,然后显示一个新的提示行。 I haven't yet found any drawbacks of using SIGALRM, but perhaps they will arise.我还没有发现使用 SIGALRM 的任何缺点,但也许它们会出现。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM