nataraj: (Default)
[personal profile] nataraj

Я люблю работать в консоли. Люблю автоматизацию скриптами. И если надо что-то массово параллельно обработать, то запустить все это в разных окнах tmux'а или screen'а, и любоваться процессом. И вот чего мне не хватало, так это возможности в каком-нибудь сложном скрипте наделать дочерних процессов и разложить их по разным окнам tmux'а. Кажется что естественная хотелка, а вот как сделать -- не понятно. И вот дошли руки разобраться как же такой фокус делается

Переносим процесс в другую консоль

Для начала рассмотрим более простую задачу: как вообще в принципе перенести процесс из одной консоли в другую. В древние времена эта задача решалась ручной перепривязкой потоков ввода-вывода процесса к другому tty или каким-то подобным образом. В современном линуксе для этого есть утилита reptyr которая автоматически стырит для вас процесс из соседнего терминала и привяжет его к текущему.

Предположим у вас есть программа:

    #!/usr/bin/perl

    print "My PID is $$\n"; # print current process PID;
    sleep 10;

    while(1){
      print ++$i, "\n";
      sleep 1;
    }

Эта программа выводит в консоль свой PID, и через некоторое время начинает в той же консоли считать секунды.

Если запустить эту программу в одной консоли, а в соседней консоли выполнить команду

reptyr [PID-number]

где PID-number номер процесса который напечатала наша тестовая программа в самом начале, то выполнение программы в исходной консоли прекратиться, а в новой продолжиться как ни в чем ни бывало.

Достаточно просто.

Перенос дочернего процесса в другую консоль

Однако если вы попробуете проделать тот же самый фокус не с отдельно работающей программой, а с дочерним процессом reptyr на вас наругается:

    [-] Process 739989 (test2.pl) shares 739990's process group. Unable to attach.
    (This most commonly means that 739990 has sub-processes).
    Unable to attach to pid 739990: Invalid argument

Дело в том, что когда вы делаете форк, порожденный процесс оказывается в одной группе с родительским процессом (и родительский процесс оказывается лидером группы), и по какой-то причине reptyr с такой ситуацией не справляется. Поэтому прежде чем тырить дочерний процесс, надо сначала вывести его из группы. Делается это вызовом setpgid, в котором дочерний процесс назначается сам себе лидером группы, и таким образом выходит из группы родительского процесса. После этого reptyr вполне справляется с переносом дочернего процесса в новую консоль.

    #!/usr/bin/perl

    use POSIX;

    $pid = fork();
    if ($pid)
    {
      # parent process
      print "Child PID is $pid\n";
      sleep 10;
      while (1) {print ".\n"; sleep 1};
    } else
    {
      # child process
      (setpgid($$,$$) != -1)           || die "Can't set own group: $!";
      sleep 10;
      while (1) {print ++$i,"\n"; sleep 1};
    }

Эта программа выводит на экран PID порожденного дочернего процесса, после чего спустя десять секунд, родительский процесс начинает выводить на экран точки с частотой один раз в секунду, а дочерний процесс начинает эти секунды вслух считать. Если не предпринимать никаких действий выводы обоих процессов будут смешаны в одной консоли, в которой их запустили.

Однако если в соседнем терминале запустить

reptyr [child-PID-number]

где child-PID-number -- PID дочернего процесса напечатанный нашей программой, то в результате вывод дочернего процесса (цифры) переедет в новую консоль, а вывод родительского процесса (точки) останется в той консоли в которой его изначально запустили.

Чего собственно говоря и хотелось добиться.

Материалы для раздумий

Date: 2024-05-09 12:08 pm (UTC)
juan_gandhi: (Default)
From: [personal profile] juan_gandhi

Роскошная идея. Спасибо.

Date: 2024-05-09 12:42 pm (UTC)
vitus_wagner: My photo 2005 (Default)
From: [personal profile] vitus_wagner

вроде же в screen это тривиально делается. Если из-под screen запустить screen команда, то в существующем screen будет для этой команды создано новое окно.

Можно еще screen -t заголовок команда

Date: 2024-05-09 03:35 pm (UTC)
vitus_wagner: My photo 2005 (Default)
From: [personal profile] vitus_wagner

Ну вот нафоркать воркеров можно путем запуска их отдельными командами, каждый в своем скрине. Вот с дождаться - сложнее, похоже синхронизатор придется свой придумывать.

Date: 2024-05-09 03:58 pm (UTC)
vitus_wagner: My photo 2005 (Default)
From: [personal profile] vitus_wagner

А как в том языке, на котором ты пишешь, с сериализацией? Вот ты питон не любишь, а в нем только в стандартной библиотеке есть по-моему три способа сериализации/восстановления объектов.

Date: 2024-05-09 04:34 pm (UTC)
vitus_wagner: My photo 2005 (Default)
From: [personal profile] vitus_wagner

Ну для этой цели скорее пойдет Storable или FreezeThaw.

Profile

nataraj: (Default)
Swami Dhyan Nataraj

July 2024

S M T W T F S
 123456
789 10111213
14151617181920
21222324252627
28293031   

Most Popular Tags

Style Credit

Expand Cut Tags

No cut tags
Page generated May. 25th, 2025 09:44 am
Powered by Dreamwidth Studios
OSZAR »