Як я можу запустити команду, яка переживе термінал близько?


313

Іноді хочеться запустити процес і забути про нього. Якщо я запускаю його з командного рядка, так:

redshift

Я не можу закрити термінал, інакше це вб'є процес. Чи можу я запустити команду таким чином, що я можу закрити термінал, не вбиваючи процес?


4
Не встановлення за замовчуванням у всіх дистрибутивах, але екран - ваш друг: en.wikipedia.org/wiki/GNU_Screen
Zayne S Halsall

Для всіх, хто стикається з тією самою проблемою: Пам’ятайте, що навіть якщо ви вводите yourExecutable &і виходи продовжують надходити на екран і Ctrl+C, здається, нічого не зупиняють, просто сліпо введіть disown;і натисніть, Enterнавіть якщо екран прокручується з виходами, і ви не бачите, що ти друкуєш. Процес буде відмовлено, і ви зможете закрити термінал, не вмираючи.
Nav

Ви можете використовувати екранний мультиплексор, такий tmux . Він доступний через apt-get на машинах ubuntu
Himanshu

Відповіді:


311

Одне з наступних 2 має працювати:

$ nohup redshift &

або

$ redshift &
$ disown

Докладніше про те, як це працює, див. Нижче.


5
Другий ( redshift & disown) працював для мене на Ubuntu 10.10. Здається, добре спрацьовуючи все це на одній лінії. Чи є якась причина, що я не повинен цього робити?
Метью

4
@Matthew Перший також повинен працювати добре, він просто не фоновий, як другий (можливо, ви хочете, nohup redshift &щоб він тло). А розміщення другого на одному рядку - це добре, хоча зазвичай ви розлучаєтесь із ;( redshift &; disown)
Майклом Мрозеком

10
@Michael: Як ;і &є командними сепараторами і мають однаковий пріоритет. Єдина відмінність - синхронне проти асинхронного виконання (відповідно). Не потрібно використовувати &;перевагу просто &(це працює, але це трохи зайве).
Кріс Джонсен

4
хороша відповідь, можна додати, що було б гарною ідеєю перенаправити stdout та stderr, щоб термінал не спамувався з виведенням налагодження
Кім

12
Також redshift &!негайно відключить червону зміну.

143

Якщо ваша програма вже запущена, ви можете призупинити її Ctrl-Z, витягніть її на другий план bgі потім виконайте disownтакі дії:

$ sleep 1000
^Z
[1]+  Stopped                 sleep 1000
$ bg
$ disown
$ exit

3
після відхилення, як я можу знову прочитати строку запущеного процесу?
Necktwi


1
З мене чомусь це не вийшло (цент)
Ян

Як вбити процес після цієї процедури?
Палак Дарджі

2
@necktwi disownне відключає stdout або stderr. Однак nohup, як і >/dev/null(відключити стандартний вихід), 2>/dev/null(відключити стандартну помилку). Він ( disown) відключає контроль роботи.
ctrl-alt-delor

45

Хорошу відповідь вже опублікував @StevenD, але я думаю, що це може трохи прояснити це.

Причина того, що процес вбивається після припинення терміналу, полягає в тому, що процес, який ви починаєте, є дочірнім процесом терміналу. Щойно ви закриєте термінал, це також знищить ці дочірні процеси. Ви можете бачити дерево процесів за допомогою pstree, наприклад, під час запуску kate &в Konsole:

init-+
     ├─konsole─┬─bash─┬─kate───2*[{kate}]
     │         │      └─pstree
     │         └─2*[{konsole}]

Щоб зробити kateпроцес відірваним від konsoleзавершення konsole, використовуйте nohupкоманду, наприклад:

nohup kate &

Після закриття konsole, pstreeбуде виглядати наступним чином :

init-+
     |-kate---2*[{kate}]

і kateвиживе. :)

Альтернативою є використання screen// tmux/ byobu, яке дозволить оболонці працювати незалежно від терміналу.


У мене були проблеми з методами відмови. Наразі це працює для мене, тому наголос. Мені це також подобається, тому що я можу хвостиком -f nohup.out, щоб побачити, що відбувається, але не переживайте за те, що мій сеанс закінчився
Ian

27

Ви можете запустити такий процес у терміналі

setsid process

Це запустить програму в новому сеансі. Як пояснено http://hanoo.org/index.php?article=run-program-in-new-session-linux


1
Якими ви бачите переваги setid перед nohup?
йогобрюс

1
1) Він не друкує дратівливе повідомлення про nohup.out. 2) Він не залишається у списку завдань вашої оболонки, тому не захаращує вихід jobs.
Мікель

Це єдине рішення, яке працювало над сценарієм, який працює у lxterminal, запускає pcmanfm та виходить (за допомогою setid термінал може закритися, поки pcmanfm продовжує працювати). Дуже дякую!
десгуа

9

Хоча всі пропозиції працюють добре, я знайшов свою альтернативу - використовувати screenпрограму, яка встановлює віртуальний термінал на екрані.

Ви можете подумати, як почати це . Екран можна встановити практично на всіх похідних Linux та Unix. Натискання + та (нижній регістр) розпочне другий сеанс. Це дозволить вам перемикатися вперед і назад між початковим сеансом натисканням клавіші + та або більш новим сеансом, натисканням клавіш + і . Ви можете мати до десяти сеансів в одному терміналі. Раніше я починав сеанс на роботі, їхав додому, схував у свою робочу машину, а потім викликав . Це підключить вас до віддаленого сеансу.screen -S session_nameCtrlACCtrlA0CtrlA1screen -d -R session_name


screen -d -m commandзапустить його у вже відокремленому екрані: ~# screen -d -m top ~# screen -ls There is a screen on: 10803..Server-station (Detached) 1 Socket in /root/.screen. ~# screen -x .... і ви приїдете.
Доктор Олександр

7

Єдиний спосіб зробити все це - закрити stdin і перетворити на команду:

command <&- & 

Тоді він не вийде, коли ви вийдете з оболонки. Перенаправлення stdout - це приємна необов'язкова річ.

Недоліком є ​​те, що ви не можете цього зробити після факту.


Я спробував у ubuntu. Термінал вбивства також закрив запущений процес. Будь-яка ідея, чому це може бути так?
Ашок Кой

7

У мене є сценарій:

  • Виконайте довільні команди у фоновому режимі

  • Не дозволяйте їм вбивати вікно терміналу

  • Придушити їх вихід

  • Обробляє стан виходу

Я використовую його в основному для gedit, evinceі inkscapeт. Д., Щоб усі мали багато дратівливих термінальних висновків. Якщо команда закінчується раніше TIMEOUT, стан виходу nohup повертається замість нуля.

#!/bin/bash

TIMEOUT=0.1

#use nohup to run the command, suppressing its output and allowing the terminal to be closed
#also send nohup's output to /dev/null, supressing nohup.out
#run nohup in the background so this script doesn't block
nohup "${@}" >/dev/null 2>&1 &
NOHUP_PID=$!

#kill this script after a short time, exiting with success status - command is still running
#this is needed as there is no timeout argument for `wait` below
MY_PID=$$
trap "exit 0" SIGINT SIGTERM
sleep $TIMEOUT && kill $MY_PID 2>/dev/null & #ignore "No such process" error if this exits normally

#if the command finishes before the above timeout, everything may be just fine or there could have been an error
wait $NOHUP_PID
NOHUP_STATUS=$?
#print an error if there was any. most commonly, there was a typo in the command
[ $NOHUP_STATUS != 0 ] && echo "Error ${@}"
#return the exit status of nohup, whatever it was
exit $NOHUP_STATUS

приклади ...

>>> run true && echo success || echo fail
success
>>> run false && echo success || echo fail
Error false
fail
>>> run sleep 1000 && echo success || echo fail
success
>>> run notfound && echo success || echo fail
Error notfound
fail

6

Я віддаю перевагу:

(applicationName &)

наприклад: linux@linux-desktop:~$ (chromium-browser &)

Обов’язково використовуйте дужки під час введення команди!


1
Закриття терміналу призведе до вбивства процесу , якого саме слід уникати ОП (і я, таким чином, сюди)
gromit190

Можливо, у вас є команда підказок, яку я використовував у своїй відповіді без дужок, якщо так закриття терміналу вбиває процес, інакше НЕ відбудеться. Я вже відредагував рішення вище, щоб зрозуміти.
даГо

робота для мене, tnx
noadev

Мені цікаво, чому це отримало не більше відгуків. nohupзапобігає будь-якому виводу Tty, і я насправді просто хотів перенаправити вихід у файл, і це завадило, щоб це було кращим рішенням для мене.
redanimalwar

4

Ви можете встановити процес (PID), щоб не отримувати сигнал HUP після виходу з системи та закриття сеансу терміналу. Використовуйте таку команду:

nohup -p PID

3

Можливо, схожий на відповідь, запропонований аполінським , я використовую варіант на screen. Команда ванілі така

screen bash -c 'long_running_command_here; echo; read -p "ALL DONE:"'

Сеанс можна від'єднати Ctrl ACtrl Dі знову підключити в простому випадку з screen -r. У мене це загорнуте у сценарій, який називається, sessionякий PATHготовий до зручного доступу:

#!/bin/bash
#
if screen -ls | awk '$1 ~ /^[1-9][0-9]*\.'"$1"'/' >/dev/null
then
    echo "WARNING: session is already running (reattach with 'screen -r $1')" >&2
else
    exec screen -S "$1" bash -c "$@; echo; echo '--------------------'; read -p 'ALL DONE (Enter to exit):'"
    echo "ERROR: 'screen' is not installed on this system" >&2
fi
exit 1

Це працює лише тоді, коли ви заздалегідь знаєте, що хочете відключити програму. Він не передбачає відключення вже запущеної програми.


2

Як і в інших відповідях, опублікованих раніше, можна перенести запущений процес на використання "екрана" заднім числом завдяки репліку та потім закрити термінал. Етапи описані в цій публікації . Слід зробити наступні кроки:

  1. Призупиніть процес
  2. Відновіть процес у фоновому режимі
  3. Відкрийте процес
  4. Запустіть сеанс на екрані
  5. Знайдіть ПІД процесу
  6. Використовуйте рептирій, щоб перейняти процес
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.