How to fire and forget a subprocess?

前端 未结 5 1287
深忆病人
深忆病人 2021-01-31 04:28

I have a long running process and I need it to launch another process (that will run for a good while too). I need to only start it, and then completely forget about it.

相关标签:
5条回答
  • 2021-01-31 05:08

    Alnitak is right. Here's a more explicit way to write it, without $$

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

    The purpose of detach is just to say, "I don't care when the child terminates" to avoid zombie processes.

    0 讨论(0)
  • 2021-01-31 05:08

    i found the answers above broke my terminal and messed up the output. this is the solution i found.

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

    just in case anyone has the same issue, my goal was to log into a ssh server and then keep that process running indefinitely. so test.sh is this

    #!/usr/bin/expect -f
    spawn ssh host -l admin -i cloudkey  
    expect "pass"
    send "superpass\r"
    sleep 1000000
    
    0 讨论(0)
  • 2021-01-31 05:12

    Detaching $$ wasn't right. From p. 348 of the Pickaxe (2nd Ed):

    $$ Fixnum The process number of the program being executed. [r/o]

    This section, "Variables and Constants" in the "Ruby Language" chapter, is very handy for decoding various ruby short $ constants - however the online edition (the first

    So what you were actually doing was detaching the program from itself, not from its child. Like others have said, the proper way to detach from the child is to use the child's pid returned from fork().

    0 讨论(0)
  • 2021-01-31 05:17

    The other answers are good if you're sure you want to detach the child process. However, if you either don't mind, or would prefer to keep the child process attached (e.g. you are launching sub-servers/services for a web app), then you can take advantage of the following shorthand

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

    Providing a block tells fork to execute that block (and only that block) in the child process, while continuing on in the parent.

    0 讨论(0)
  • 2021-01-31 05:34

    The fork function separates your process in two.

    Both processes then receive the result of the function. The child receives a value of zero/nil (and hence knows that it's the child) and the parent receives the PID of the child.

    Hence:

    exec("something") if fork.nil?
    

    will make the child process start "something", and the parent process will carry on with where it was.

    Note that exec() replaces the current process with "something", so the child process will never execute any subsequent Ruby code.

    The call to Process.detach() looks like it might be incorrect. I would have expected it to have the child's PID in it, but if I read your code right it's actually detaching the parent process.

    0 讨论(0)
提交回复
热议问题