task icon indicating copy to clipboard operation
task copied to clipboard

`&` at the end of `cmd` doesn't run the command in background

Open Mussabaheen opened this issue 3 years ago • 15 comments

Thanks for your bug report!

Before submitting this issue, please make sure the same problem was not already reported by someone else.

Please describe the bug you're facing. Consider pasting example

when using & at the end of a command doesn't make it a background task.

Taskfiles showing how to reproduce the problem.

run:
   cmds:
     - task: build
     - echo "Running server..."
     -  ./{{.APP_NAME}} > out.txt &
     - echo "Server running..."
  • Task version: latest
  • Operating System: macOS and Linux

Mussabaheen avatar Nov 10 '22 10:11 Mussabaheen

ok so, I found the problem basically the task ends before the server can start may be we should add the support for disown in this

Mussabaheen avatar Nov 10 '22 15:11 Mussabaheen

This appears to be an issue with mvdan/sh. See replication steps below:

service.sh:

#!/bin/bash
for i in {1..5}; do sleep 1s && echo "$i"; done

> bash -c "./service.sh > out.txt &":

Creates the file out.txt and appends the numbers 1..5 as a background process

> gosh -c "./service.sh > out.txt &":

Does nothing :/

pd93 avatar Nov 10 '22 19:11 pd93

I think the problem is that the parent task ends and it forces the child process created using & to end as well.

Mussabaheen avatar Nov 11 '22 09:11 Mussabaheen

I don't think this is to do with Task. As I said, this problem also exists when executing your command directly with gosh (the interpreter used by Task).

Also, if we write a Taskfile like this:

version: '3'

tasks:
  sleep-5s-bg:
    cmds:
      - sleep 5s &

  ps:
    cmds:
      - ps

and then run

> task sleep-5s-bg > task ps

task: [ps] ps
    PID TTY          TIME CMD
...
 416575 pts/1    00:00:00 task
 416583 pts/1    00:00:00 sleep

You can see that the task executes sleep in the background and exits, but if you check ps, the sleep process is still running (i.e. Task is not killing the process when it exits).

This appears to only be a problem with combining redirection (> somefile) with job control (&)

pd93 avatar Nov 11 '22 10:11 pd93

I was able to reproduce the issue without using redirection.

This task does not start dolphin by some reason.

dolphin:
  cmds:
   - 'dolphin . &'

The workaround is appending some dummy command to the main one.

dolphin:
  cmds:
   - 'dolphin . &'
   -  ':'

Chi-teck avatar Jan 17 '23 18:01 Chi-teck

Ran into this starting up an express process in the background. Adding something like sleep 10 after the & works, but it seems to be relative to the OS-level process setup time.

toddpi314 avatar Feb 03 '23 15:02 toddpi314

I also ran into this issue, but none of the workarounds seem to work consistently (adding a dummy : task, or adding a sleep 5).

pyrho avatar Feb 22 '23 17:02 pyrho

I was just about to create my first task and stumbled across this problem. I have now actually invested 2 hours to find the error, as I never thought that it was due to the task file or the interpreter. Unfortunately, the workaround with : does not work for me. I just checked the docs, but could not find something like this: Is there an option to disable mvdan/sh and use /bin/bash or /bin/sh directly?

matzeeable avatar Mar 21 '23 07:03 matzeeable

Would it be possible to defer a call to wait with the pid of the command? Trying to think of how you would get the pid to the wait command though.

q0rban avatar Aug 09 '23 14:08 q0rban

I tried this, and I couldn't get the pid without using a sub-subshell (not sure why?), and since the defer tasks are run in a different subshell, it's not possible to wait for it.

version: 3

tasks:
  default:
    cmds:
      - mkdir -p run
      - for: [chicken, duck]
        task: process-item
        vars:
          ITEM: '{{.ITEM}}'

  process-item:
    cmds:
      - |
        sh -c 'sleep 30 &
        echo $! > run/{{.ITEM}}'
      - echo {{.ITEM}}
      - defer: bash -c "wait $(cat run/{{.ITEM}})"

Output:

$ task
task: [default] mkdir -p run
task: [process-item] sh -c 'sleep 30 &
echo $! > run/chicken'

task: [process-item] echo chicken
chicken
task: [process-item] bash -c "wait $(cat run/chicken)"
bash: wait: pid 83816 is not a child of this shell
task: [process-item] sh -c 'sleep 30 &
echo $! > run/duck'

task: [process-item] echo duck
duck
task: [process-item] bash -c "wait $(cat run/duck)"
bash: wait: pid 83820 is not a child of this shell

q0rban avatar Aug 09 '23 16:08 q0rban

I couldn't get the pid without using a sub-subshell (not sure why?)

Okay, I discovered the reason we can't get the pid: mvdan/sh#221

This library is written in Go, so it can't spawn sub-processes.

q0rban avatar Aug 11 '23 12:08 q0rban

It works if you run in bg both the subcommand in the subshell and the subshell itself, followed by sleep:

task test_bg
task: [test_bg] bash -c 'sleep 10 & echo "PID $!"'& sleep 1
[test_bg] PID 4213

ps -fp 4213
UID     PID    PPID  TTY        STIME COMMAND
cri    4213       1 cons1    12:33:17 /usr/bin/sleep

or, simpler, no PID output:

task test_bg
task: [test_bg] $(sleep 10&)& sleep 1

ps -ef| grep sleep
cri    4367       1 cons1    12:43:49 /usr/bin/sleep

Tested on both Windows and Linux.

See https://github.com/go-task/task/issues/162

cr1cr1 avatar Jan 02 '24 10:01 cr1cr1

what is the solution to spawn a disowned process ?

leobenkel avatar Mar 13 '24 13:03 leobenkel

@leobenkel this worked for me:

  start-ollama:
    cmds:
      - bash -c 'nohup ollama serve >/dev/null 2>&1 &'

JonZeolla avatar Apr 26 '24 16:04 JonZeolla