Несколько экземпляров одной и той же программы, получающей выход

Отличие могло быть в файле / etc / sudoers. Возможно, вашему пользователю разрешено запускать kill с nopasswd на одной машине, но не на другой.

2
13.07.2018, 10:31
1 ответ

Насколько я понимаю, ваши требования заключаются в том, чтобы иметь возможность:

  1. Одновременный запуск нескольких экземпляров программы.
  2. Получите терминальный контроль над любым из экземпляров в любое время.
  3. Отправка экземпляров обратно в фоновый режим сразу после их вывода.

Если придерживаться подхода &, то да, есть сокращение для (3 ). Когда программа контролирует терминал, ее можно перевести в фоновый режим с помощью сигнала SIGTSTP. Достаточно удобно, что обычно это делает Ctrl + Z .

Следовательно, у вас может быть что-то вроде этого:

$ foo &
Welcome
[1] 10

$ foo &
Welcome
[2] 11

$ fg %1
<ENTER>
Time now is 01:23:45
<Ctrl+Z>
[1]+ Stopped

Насколько мне известно, дляfg(такого ярлыка нет, и как бы вы все равно указали, какой экземпляр вернуть?)

Обратите внимание, что сигнал SIGTSTPна самом деле не обязательно должен исходить от оболочки, которая запустила процесс. Если вы kill -TSTPзапустите процесс по PID во второй оболочке, вы также сможете вернуть его с помощью fgв первой.

I need to put it back to background after obtaining the latest output of the program (by pressing any button: is there any method to do this programmatically?)

Если под программно вы подразумеваете, что у вас есть доступ к исходному коду foo, тогда вы можете использовать то, что мы только что видели. Системный вызов raiseможет использоваться программой для отправки сигнала самой себе. Если мы возьмем очень упрощенную версию foo, у нас может быть что-то вроде этого:

#include <stdio.h>
#include <signal.h>

int main(void)
{
    printf("Welcome");
    while(getchar()) { /* Use termios to switch to unbuffered mode */
        fprintf(stdout, "The time is... something");
        fflush(stdout);
        fflush(stdin);
        raise(SIGTSTP);
    }

    return 0;
}

Теперь, хотя все это достаточно хорошо, я согласен, что screen, вероятно, лучший способ сделать все это, в основном потому, что вы можете называть свои сеансы экрана и, следовательно, никогда не нужно запоминать идентификатор задания или процесса. Как и подход &, он также имеет то преимущество, что не требует внесения изменений в исходный код.

$ screen -S foo1
$./foo
Welcome
<Ctrl-a d>
[detached from 10.foo1]

$ screen -s foo1
<ENTER>
Time now is 01:23:45
<Ctrl-a d>
[detached from 10.foo1]

Еще одно преимущество заключается в том, что вам не нужно останавливать программу перед отсоединением. Это довольно удобно, если вы хотите, чтобы он делал что-то в фоновом режиме, пока вы не смотрите. В предыдущем подходе вам нужно было бы запускать bgкаждый раз, когда вы останавливаете foo.

Вы также можете получить список запущенных экранов с помощью screen -ls. На моей машине я установил несколько псевдонимов в ~/.bashrc, чтобы учесть мою дополнительную лень :

.
alias S='screen -S'
alias s='screen -r'
alias sls='screen -ls'

Таким образом, вы могли бы просто делать такие вещи, как S foo1, s foo1,... Некоторые могут возразить, что псевдонимы одного символа -могут немного раздражать, когда вы неправильно ставите пробел или что-то в своих командах, но я думаю screenявляется одной из тех программ, которые настолько удобны , что вы можете позволить себе сделать исключение.

Теперь, предположив, что вы используете screenподход, вот как вы можете отправить ключ в сеанс и получить его последнюю строку вывода из оболочки. Есть способы настроить это (, и я позволил себе несколько сокращений ), но тем не менее. Вы можете определить следующую функцию в~/.bashrc:

screen_key_tail() {
    screen -S $1 -X stuff "^M"
    tmp="$(mktemp)"
    screen -S $1 -X hardcopy "$tmp"
    grep -v ^$ "$tmp" | tail -n1
    rm "$tmp"
}

и вызовите его с помощью:

$ screen_key_tail foo1

, где foo1— имя сеанса screen, на который вы ориентируетесь.

2
27.01.2020, 22:17

Теги

Похожие вопросы