简体   繁体   中英

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> .

$ 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. Running a non-blocking command like wait :

$ sleep 60 & wait

then sending the signal causes wait to terminate immediately, followed by the output of the handler.

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.

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. 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.

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 :

$ dtach -a /tmp/MySocket bash -i

Now from terminal A, we can send a message to the bash session in terminal B like so :

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

In terminal B, we now see :

$ echo hello
hello

To expand on that if I now do in terminal A :

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

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

It may be buffering.

As a test, try installing a loop trigger. In window A:

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

in window B:

 kill -usr1 7316

back in window A the ls is firing when the loop does an echo. 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'. 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. I tried SIGINT, but that caused an annoying "^C", followed by a new prompt line, to be displayed. I haven't yet found any drawbacks of using SIGALRM, but perhaps they will arise.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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