If I do this from the shell:

$ sleep 100

I can make it go to the background by doing:

$ bg

And then continue using my shell. You can get the same effect by adding a & to the end of the command, but I often forget this.

In Vim, I often do:

:!sleep 100

And here also, I often forget to add the &. Can I put this process in the background and continue using Vim like in the shell?

  • 1
    To avoid forgetting again, you could ask Vim to append & every time: :nnoremap :! :!&<Left> ... But of course, sometimes you won't want the &, and will have to hit <Del>to remove it. – joeytwiddle Feb 24 '15 at 21:41
  • @joeytwiddle That's a good idea, and sounds like something you could write as an answer, instead of just a comment :-) – Martin Tournoij Feb 24 '15 at 21:43

As <C-z> will suspend Vim itself, not just the launched shell command, that won't work.

What I would do is abort the long-running command with <C-c>, then relaunch the same command in the background via

:!! &

(The :!! command comes handy for recalling the previous external command here; you could also use the Ex command history via <Up>.)

  • 1
    This is exactly the workflow I'm hoping to improve on. The problem is that you need to close whatever you started... – Martin Tournoij Feb 24 '15 at 14:27

You can put the command in a shell script that backgrounds itself. The contents, for example, might be:

sleep 100 &
  • 3
    Which would be of not much use once the command has already started. – muru Feb 24 '15 at 7:04
  • I mean that one could run the shell script instead of the slow command. Having it background itself obviates the need to remember to do it at run time. I guess I'm not understanding the use case very well. If it's the same command that I keep forgetting to background, I'd use the shell script. If this is happening with arbitrary commands, I'd consider making a habit of switching to an actual shell to do so. – Jon Carter Feb 24 '15 at 7:10
  • I use tmux by default, but problem is that my Vim session (with open files and such) is still useless. I could switch to another pane, and run my script there, but that are a lot more actions than :!gitk % for example... The thing with using scripts is that I would have to pre-create many of these scripts for every possible command. Perhaps it's not a bad idea for some of the most used commands (such as gitk & mupdf) though. – Martin Tournoij Feb 24 '15 at 8:11

Normally when a process is started, you don't have much control on it other than terminating it (Ctrl+c) or suspending it (Ctrl+z, but including the parent process).

However depending on the process type and operating system, here are few tricks that you can try:

  • Sending SIGTSTP or SIGSTOP will stop the process (the same signal sent by Ctrl+z), and SIGCONT will continue (resume) the process. Testing with sleep doesn't work, so you've to test it with specific software how it handles the signals. E.g.

    killall -SIGSTOP sleep
    killall -SIGTSTP sleep
    kill -SIGTSTP PID

    SIGSTOP stop process stop (cannot be caught or ignored)

    SIGTSTP stop process stop signal generated from keyboard

  • Sending SIGHUP to the process. By default this signal terminates the process, however if the process implements SIGHUP signal, it should detach from controlling tty and re-run in the background with new process id (usually it's used with daemons). Unfortunately many applications do not handle it correctly and simply die (including sleep). E.g.

    killall -SIGHUP sleep

    SIGHUP terminate process terminal line hangup

  • Other solution could use tools such as retty (reattach to a pseudo-tty), detach (detaches a process from the terminal), nohup (disconnects the process from the terminal) or gdb (attach to existing process -p and close its file descriptors such as tty, similar example).

For more info, check: Job control (Unix) - Implementation at Wikipedia.

See also: man kill or man sigaction.

  • It's weird that this works for you—it shouldn't. STOP/CONT should just pause and resume the process, nothing more. It doesn't work here, in either console vim or gvim. – derobert Feb 24 '15 at 16:46

Note: This answer only seems to work with the tcsh and fish shells. I also tried bash, dash, mksh, and zsh, and it doesn't work there; I'm not sure why, because if I do the same actions from these shells without Vim, it does work as expected... (:! commands are executed though the shell).

I happen to use tcsh, so it works for me...

You can use :set shell=/bin/tcsh to set your shell; this is global, though. So only use it if you think this is a very important feature :-)

^Z send a SIGTSTP signal, you can send this signal with kill, and then use SIGCONT to continue (resume) the process. This will detach the process from Vim.

Because it's difficult to show with this sleep (how do you know it has continued execution?), I'll use gitk as an example (but any GUI program will do):

For example in Vim:

:!gitk %

And then in another terminal:

$ ps ax | grep gitk
30105 pts/10   S+     0:00 -bin/tcsh -c gitk
30108 pts/10   Sl+    0:00 wish /sbin/gitk --

$ kill -TSTP 30108
$ kill -CONT 30108

You can of course also use killall, or pkill; for example:

$ killall -TSTP wish
$ killall -CONST wish

You do need to open another terminal for this, which is not ideal, but it will allow you to continue using both your Vim and your external process.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.