Чому деякі команди "зависають" термінал до їх закінчення?


22

Іноді ви запускаєте програму з терміналу, скажімо, lxpanel . Термінал не поверне вас до підказки, він зависне. Ви можете натиснути Ctrl+, Cщоб повернутися до підказки, але це вб'є lxpanel. Однак натискання клавіші Alt+ F2(що спливає вікно, щоб взяти команду) і запуск lxpanelпрацює витончено.

Чому це? Що відрізняється між запуском команди з терміналу і вікном 'run', яке з’являється при натисканні Alt+ F2?

lxpanel тут був просто використаний як приклад. Я переживав це з кількома програмами


1
Порада: GNU Screen ( screen) може, крім іншого, використовуватися для "обгортання" триваліших процесів. Ви можете від'єднатись від нього, повернувшись до оболонки, після чого повторно приєднайте та побачите вихід із запущеного процесу. Повторне приєднання може бути здійснено навіть з іншого терміналу, SSH тощо. Можуть бути й інші програми, які дозволяють вам робити подібні речі.
poplitea

Відповіді:


28

За замовчуванням термінал запустить програму на передньому плані, тому ви не опинитеся в оболонці, поки програма не закінчиться. Це корисно для програм, які читають зі stdin та / або записують у stdout - зазвичай ти не хочеш, щоб багато з них працювали одразу. Якщо ви хочете, щоб програма запускалася у фоновому режимі, ви можете запустити її так:

$ lxpanel &

Або якщо він вже запущений, ви можете призупинити його з Ctrl+, Zа потім запустіть, bgщоб перемістити його на другий план. Так чи інакше, у вас з’явиться новий запит на оболонку, але програма все ще працює, і її вихід з’явиться в терміналі (так що він може раптом відобразитися, коли ви знаходитесь в середині вводу)

Деякі програми (як правило, демони) під час запуску розгортають окремий процес, а потім дозволяють головному процесу негайно вийти. Це дозволяє програмі продовжувати працювати, не блокуючи оболонку


Отже, що насправді робить система, коли ви запускаєте програму через вікно 'run', натискаючи Alt + f2? (принаймні, на gnome та openbox, це робить alt + f2). Я прошу, тому що як тільки ви введете команду, програма запускається, і поле відходить. це просто додавання & до нього?
sqram

2
@lyrae: за замовчуванням оболонка очікує завершення програми перед продовженням сеансу оболонки, вона не "висить", за будь-яким визначенням "висіти"; alt + f2 не чекає програми. Причина, що оболонка чекає завершення програми, полягає в тому, що оболонка може перенаправляти все, що користувач ввів у оболонку, на стандартний вхід програми та / або стандартний вихід програми. Оскільки alt + f2 в основному використовується для запуску програми GUI, alt + f2 не передбачає можливості використання стандартного вводу / виводу, тому його не потрібно чекати.
Лежи Райан

1
@lyrae: alt + f2 не робить нічого особливого для запуску програми у фоновому режимі; саме оболонка робить щось особливе, додавання "&" - це функціональність оболонки. Запускаючи команду без знака "&", оболонка перенаправляє стандартний вхід програми на власний стандартний вхід, а стандартний вихід програми на власний стандартний вихід (трохи надуманий, оскільки оболонка також надає безліч інших послуг, таких як перехоплення Ctrl -C, щоб надіслати команду сигналу SIGINT програмі переднього плану). '&' Вказує оболонці не робити цих дій і просто запустити програму (також надумано).
Лі Лі Райан

1
@LieRyan Деякі з того, що ви говорите, оболонка, насправді обробляється драйвером терміналу ядра, а "з &", як правило, більше "спеціальне", ніж "без &", крім того, що оболонка викликає wait () [або waitpid або еквівалент], що не робиться за допомогою alt-f2.
Випадково832

6

Коли ви запускаєте програму в терміналі, термінал буде «висіти», поки ваша програма не зупиниться. Натискаючи клавішу Ctrl+, cви закриваєте свою програму і тим самим повертаєтесь до підказки. Ви побачите це з усіма програмами GUI, спробуйте, наприклад, Firefox.

Якщо ви використовуєте якийсь інший метод, наприклад, Alt + F2 або клацаєте через меню, ваша програма запускається у фоновому режимі, тому нічого дивного не відбувається (і командного рядка все одно немає).

Якщо ви все ще хочете запускати програми GUI з терміналу, додайте &наприкінці вашої команди так

lxpanel &

Це говорить про те, що термінал працює lxpanelу фоновому режимі і негайно дає вам ще одне підказку.


3

Програми запускаються через оболонку, запущену на передньому плані цієї оболонки за замовчуванням. Це змушує оболонку призупиняти роботу і направляти stdin / stdout / sterr з терміналу в програму. Програми, що працюють через робоче середовище, роздвоєні , що призводить до того, що вони запускаються незалежно від програми, яка їх запускала. Це можна змоделювати в більшості оболонок, додавши &команду, хоча це все одно з'єднає std * до терміналу (хоча читання з stdin у фоновій програмі має додаткові ускладнення).


2

Добре і фони, за винятком програм, які повертаються, які потребують взаємодії консолі пізніше (наприклад, "влучне оновлення &", яке врешті-решт переходить у стан STOP, оскільки воно хоче сповістити користувача на запитання "справді насправді?" Набагато пізніше .... коли вже ніхто не дивиться).

Щоб підключити цю дірку і повідомити про процес, термінал дійсно ніколи не стане доступним для нього, я додаю <& - до деяких моїх команд, повністю від'єднуючи їх від активного терміналу, кажучи, що STDIN вже не можливий. Переконайтесь, що / bin / bash - це ваша оболонка, якщо ви її використовуєте. Сценарій здійснюватиме реєстрацію будь-яких помилок, пов’язаних із відсутністю псевдотерміналу, на якому можна подавати будь-яке підказку.

Наприклад:

`./runme.sh &> runme.log <&- & disown`

це мій остаточний спосіб відмежуватися від поточного термінального сеансу. І STDOUT, і STDERR потрапляють до runme.log, неважливо, чи швидше закінчиться ваша консоль або оболонка чи ви вийдете / su в інший обліковий запис (немає термінального сміття з runme), а завдяки відмови навіть від батька-батька PID-зв’язок видалено.

ОНОВЛЕННЯ: навіть з цим у мене виникли проблеми з семафором, асоціюючи його з іменем початкового батька, тому тепер рекомендую замість цього:

at now <<< "(cmd1; cmd2; etc.) &> logfile.log"

Звичайно, видаліть &>, якщо ви хочете отримати електронною поштою вихід з CRON, або перенаправіть все це на / dev / null замість файлу.


Трохи менш складний спосіб досягти того, що я почав використовувати,at now <<< "(cmd1; cmd2; etc.) &> logfile.log"
Маркос
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.