Вопрос

У меня давно запущенный процесс, и он нужен мне для запуска другого процесса (который тоже будет работать довольно долго).Мне нужно только начать это, а потом полностью забыть об этом.

Мне удалось сделать то, что мне было нужно, взяв немного кода из книги по программированию на Ruby, но я хотел бы найти наилучший / правильный способ и понять, что происходит.Вот что у меня получилось изначально:

exec("whatever --take-very-long") if fork.nil?
Process.detach($$)


Итак, так ли это, или как еще я должен это сделать?

После проверки приведенных ниже ответов я в итоге получил этот код, который, кажется, имеет больше смысла:

(pid = fork) ? Process.detach(pid) : exec("foo")


Я был бы признателен за некоторые объяснения о том, как fork работает.[это я уже понял]

Отделялся $$ верно?Я не знаю, почему это работает, и мне бы очень хотелось лучше разобраться в ситуации.

Это было полезно?

Решение

Тот Самый fork функция разделяет ваш процесс надвое.

И то , и другое затем процессы получают результат выполнения функции.Дочерний элемент получает нулевое значение/nil (и, следовательно, знает, что это дочерний элемент), и родитель получает PID дочернего элемента.

Следовательно:

exec("something") if fork.nil?

заставит дочерний процесс запустить "что-то", а родительский процесс продолжит с того места, где он был.

Обратите внимание , что exec() заменяет текущий процесс с "чем-то", поэтому дочерний процесс никогда не будет выполнять какой-либо последующий код Ruby.

Призыв к Process.detach() похоже, это может быть неверно.Я бы ожидал, что в нем будет PID дочернего процесса, но если я правильно прочитал ваш код, это фактически отсоединяет родительский процесс.

Другие советы

Алнитак прав.Вот более явный способ написать это, без $$

pid = Process.fork
if pid.nil? then
  # In child
  exec "whatever --take-very-long"
else
  # In parent
  Process.detach(pid)
end

Цель отсоединения - просто сказать: "Мне все равно, когда ребенок завершит работу", чтобы избежать процессы зомбирования.

Отсоединение $$ это было неправильно.Из п.348 о Кирке (2-е изд.):

$$ Fixnum - номер процесса выполняемой программы.[r/o]

Этот раздел "Переменные и константы" в главе "Язык Ruby" очень удобен для декодирования различных сокращений ruby $ константы - однако онлайн-издание (первое

Итак, то, что вы на самом деле делали, это отсоединяли программу от самой себя, а не от ее дочернего элемента.Как уже говорили другие, правильный способ отсоединиться от дочернего элемента - это использовать pid дочернего элемента, возвращенный из fork().

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

fork do
    exec('whatever --option-flag')
end

Предоставление блока указывает fork выполнить этот блок (и только этот блок) в дочернем процессе, продолжая работу в родительском.

я нашел приведенные выше ответы, которые сломали мой терминал и испортили вывод.это решение, которое я нашел.

   system("nohup ./test.sh &")

на всякий случай, если у кого-то возникнет такая же проблема, моей целью было войти на ssh-сервер, а затем сохранить этот процесс запущенным на неопределенный срок.итак, test.sh это

#!/usr/bin/expect -f
spawn ssh host -l admin -i cloudkey  
expect "pass"
send "superpass\r"
sleep 1000000
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top