Добрый день.
Есть скрипт запускающий программу с консольным вводом-выводом. Если во время выполнения программы нажать Ctrl-C, на экран вылезет ^C. Если просто в терминале жать Ctrl-C - выдается просто перевод строки. Перенапрвление ввода-вывода не спасает. Я смотрел исходники, hfpltk документации Job control, но так и не понял: в каких случаях выдаются контрольные последовательности, а в каких нет. Есть идеи?
Обработка сигналов в Bash
Модераторы: /dev/random, Модераторы разделов
-
nesk
- Сообщения: 2268
- Статус: Линукссаксовец
- ОС: MS Windows XP Home SP3
Re: Обработка сигналов в Bash
savigm писал(а): ↑25.03.2009 18:55Добрый день.
Есть скрипт запускающий программу с консольным вводом-выводом. Если во время выполнения программы нажать Ctrl-C, на экран вылезет ^C. Если просто в терминале жать Ctrl-C - выдается просто перевод строки. Перенапрвление ввода-вывода не спасает. Я смотрел исходники, hfpltk документации Job control, но так и не понял: в каких случаях выдаются контрольные последовательности, а в каких нет. Есть идеи?
trap
Код:
trap [-lp] [[arg] sigspec ...]
The command arg is to be read and executed when the shell
receives signal(s) sigspec. If arg is absent (and there is a
single sigspec) or -, each specified signal is reset to its
original disposition (the value it had upon entrance to the
shell). If arg is the null string the signal specified by each
sigspec is ignored by the shell and by the commands it invokes.
If arg is not present and -p has been supplied, then the trap
commands associated with each sigspec are displayed. If no
arguments are supplied or if only -p is given, trap prints the
list of commands associated with each signal. The -l option
causes the shell to print a list of signal names and their cor-
responding numbers. Each sigspec is either a signal name
defined in <signal.h>, or a signal number. Signal names are
case insensitive and the SIG prefix is optional. If a sigspec
is EXIT (0) the command arg is executed on exit from the shell.
If a sigspec is DEBUG, the command arg is executed before every
simple command, for command, case command, select command, every
arithmetic for command, and before the first command executes in
a shell function (see SHELL GRAMMAR above). Refer to the
description of the extdebug option to the shopt builtin for
details of its effect on the DEBUG trap. If a sigspec is ERR,
the command arg is executed whenever a simple command has a
non-zero exit status, subject to the following conditions. The
ERR trap is not executed if the failed command is part of the
command list immediately following a while or until keyword,
part of the test in an if statement, part of a && or || list, or
if the command's return value is being inverted via !. These
are the same conditions obeyed by the errexit option. If a
sigspec is RETURN, the command arg is executed each time a shell
function or a script executed with the . or source builtins fin-
ishes executing. Signals ignored upon entry to the shell cannot
be trapped or reset. Trapped signals that are not being ignored
are reset to their original values in a child process when it is
created. The return status is false if any sigspec is invalid;
otherwise trap returns true.
Внимание: У меня под рукой нет машины с Linux. Я не использую эту ОС. Ответы я даю либо по памяти, либо мне помогает гугл. Тщательно читайте маны по тем командам и конфигурационным файлам, которые я упоминаю.
0xDEFEC8ED
0xDEFEC8ED
-
savigm
- Сообщения: 127
- ОС: openSUSE
Re: Обработка сигналов в Bash
Поясню подробней: скрипт запускает программу с перенапрвлением выдачи в файл. Если не жать [CTRL]+[C], а послать процессу программы (не скрипта) сигнал SIGINT - kill -2 <PID>, то все нормально, программа завершается, на терминал никаких ^C не выводится. Если с клавы вводить [CTRL]+[C] выодится ^C. В этом собственно и проблема, мне нужно чтобы ^C на экран не выдавалось, а программа завершалась по этому сигналу, и скрипт продолжал выполнять следующие команды.
-
savigm
- Сообщения: 127
- ОС: openSUSE
Re: Обработка сигналов в Bash
Копал не в том напрвлении: ^C видимо bash'ом нормально обрабатывается без выдачи на терминал, а вот при выполнении программы за это отвечает настройка консоли, а точнее keymaps. У меня кодировка KOI8-R и keymap - ru1.map.gz(выбрал, т.к. в консоли нормально обрабатывет backspace, ru.map.gz отображает ^H). Видимо надо настраивать раскладку.
-
savigm
- Сообщения: 127
- ОС: openSUSE
Re: Обработка сигналов в Bash
Или всетаки bash выдает ^C на терминал, когда запущена программа и она не имеет своего обработчика сигнала SIGINT? Вот интересный кусочек из исходников bash - файл jobs.c:
Точнее даже не bash, а ядро, судя по комментарию:
/* If job control is enabled, the job was started with job
control, the job was the foreground job, and it was killed
by SIGINT, then print a newline to compensate for the kernel
printing the ^C without a trailing newline. */
Правда все это относится к job control в Bash, но суть наверно та же и для foreground процессов.
Выходит, что в моем случае не bash выдает ^C, а ядро, оно же судя по всему и обрабатывает сигнал SIGINT.
Однако это верно только в случае посылки сигнала с клавиатуры - [Ctrl]+[C], в случае посылки kill'ом SIGINT'а сигнал обрабатывает bash, ничего не выводя на терминал.
Код:
/* If job control is enabled, the job was started with job
control, the job was the foreground job, and it was killed
by SIGINT, then print a newline to compensate for the kernel
printing the ^C without a trailing newline. */
if (job_control && IS_JOBCONTROL (job) && IS_FOREGROUND (job) &&
WIFSIGNALED (s) && WTERMSIG (s) == SIGINT)
{
/* If SIGINT is not trapped and the shell is in a for, while,
or until loop, act as if the shell received SIGINT as
well, so the loop can be broken. This doesn't call the
SIGINT signal handler; maybe it should. */
if (signal_is_trapped (SIGINT) == 0 && loop_level)
ADDINTERRUPT;
else
{
putchar ('\n');
fflush (stdout);
}
}
Точнее даже не bash, а ядро, судя по комментарию:
/* If job control is enabled, the job was started with job
control, the job was the foreground job, and it was killed
by SIGINT, then print a newline to compensate for the kernel
printing the ^C without a trailing newline. */
Правда все это относится к job control в Bash, но суть наверно та же и для foreground процессов.
Выходит, что в моем случае не bash выдает ^C, а ядро, оно же судя по всему и обрабатывает сигнал SIGINT.
Однако это верно только в случае посылки сигнала с клавиатуры - [Ctrl]+[C], в случае посылки kill'ом SIGINT'а сигнал обрабатывает bash, ничего не выводя на терминал.
-
Rootlexx
- Бывший модератор
- Сообщения: 4471
- Статус: GNU generation
- ОС: Debian GNU/Linux