bash: запускать несколько цепочек команд в фоновом режиме - PullRequest
43 голосов
/ 02 октября 2008

Я пытаюсь запустить некоторые команды в параллельном режиме, в фоновом режиме, используя bash. Вот что я пытаюсь сделать:

forloop {
  //this part is actually written in perl
  //call command sequence
  print `touch .file1.lock; cp bigfile1 /destination; rm .file1.lock;`;
}

Часть между обратными галочками (``) порождает новую оболочку и последовательно выполняет команды. Дело в том, что управление исходной программой возвращается только после выполнения последней команды. Я хотел бы выполнить весь оператор в фоновом режиме (я не ожидаю каких-либо выходных / возвращаемых значений) и хотел бы, чтобы цикл продолжал выполняться.

Вызывающая программа (та, которая имеет цикл) не завершится, пока не завершатся все порожденные оболочки.

Я мог бы использовать потоки в Perl для создания разных потоков, которые вызывают разные оболочки, но это кажется излишним ...

Могу ли я запустить оболочку, дать ей набор команд и сказать ей перейти в фоновый режим?

Ответы [ 14 ]

1 голос
/ 04 октября 2008

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

my @children;
for (...) {
    ...
    my $child = fork;
    exec "touch .file1.lock; cp bigfile1 /destination; rm .file1.lock;" if $child == 0;
    push @children, $child;
}
# and if you want to wait for them to finish,
waitpid($_) for @children;

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

Кстати,

print `some command`

и

system "some command"

выводит то же содержимое в stdout, но первое имеет более высокие издержки, так как Perl должен захватить весь вывод "some command"

1 голос
/ 02 октября 2008

Попробуйте поместить команды в фигурные скобки с & s, например:

{command1 & ; command2 & ; command3 & ; }

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

НТН

0 голосов
/ 01 ноября 2014

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

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

$ ls *|parallel -kj0 --eta 'cp {} /tmp/destination'

Поскольку мы использовали опцию -j0, все файлы будут копироваться параллельно. В случае, если вам нужно уменьшить количество параллельных процессов, вы можете использовать -j<n>, где <n> - номер параллельного процесса, который будет выполнен.

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

Опция

--eta предоставит вам подробную статистику происходящего процесса. Таким образом, мы можем знать, как мог завершиться процесс и сколько времени потребуется, чтобы закончить.

0 голосов
/ 27 октября 2014

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

print `touch .file1.lock && cp bigfile1 /destination && rm .file1.lock &`;
...