Блокировка запуска терминала

Если вы введете эту простую тестовую команду:

gnome-terminal -x bash -c "ls;sleep 3"

Вы обнаружите, что она немедленно возвращается (вновь созданный терминал, конечно, задерживается на три секунды). Это, в отличие от, скажем, rxvt (та же команда, но с e).

Если вы хотите начать блокировку, исторический консенсус, похоже, использовал --disable-factory . К сожалению, это больше не работает (протестировано 3.14.2).

Итак, как мне запустить терминал асинхронным способом?

Бонус: konsole, lxterminal и xfce4-terminal, по крайней мере, также имеют те же проблема. Команды для тех?

5
задан 23 May 2017 в 15:39

5 ответов

Я использую метод, который имеет некоторые общие черты ответу terdon (и был создан с некоторой справкой его - Спасибо @terdon для этого!), но имеет немного отличающийся подход:

я создаю временный файл так, чтобы дочерний терминал мог связаться с родительским терминалом и сказать ему PID своего соответствующего экземпляра удара. Тогда я позволяю родительскому терминалу считать временный файл и помнить PID, удалить файл и продолжиться путем проверки каждых 100 мс (задержка может быть изменена), работает ли экземпляр удара дочернего терминала все еще. В противном случае терминал был закрыт или вручную или потому что законченная команда. Тогда запускающиеся концы команды и родительский терминал применимы снова.

Преимущество этого подхода:
Все команды, которые будут запущены (ls; sleep 3 или любая замена для тех) выполняются после команда, которая ответственна для разрешения обнаружения терминального закрытия. Таким образом, если внутренняя команда зависает, или Вы закрываете терминал вручную, прежде чем это закончится, механизм все еще работает и продолжит выполнение внешнего сценария вместо того, чтобы столкнуться с бесконечными циклами.

<час>

код, поскольку острота с выводом отладки ("запущенный" после того, как дочернее окно терминала было открыто, "завершилась" после того, как это было закрыто), и точность 0,1 секунд:

pidfile=$(mktemp); gnome-terminal -x bash -c "echo \$>$pidfile; ls; sleep 3"; until [ -s $pidfile ]; do sleep 0.1; done; terminalpid=$(cat "$pidfile"); rm $pidfile; echo "launched"; while ps -p $terminalpid > /dev/null 2>&1; do sleep 0.1; done; echo "terminated"

Или без отладки произведите:

pidfile=$(mktemp); gnome-terminal -x bash -c "echo \$>$pidfile; ls; sleep 3"; until [ -s $pidfile ]; do sleep 0.1; done; terminalpid=$(cat "$pidfile"); rm $pidfile; while ps -p $terminalpid > /dev/null 2>&1; do sleep 0.1; done

Почти тот же код, но с большей гибкостью, записанной как сценарий удара:

#! /bin/bash

delay=0.1
pidfile=$(mktemp)

gnome-terminal -x bash -c "echo \$>$pidfile; ls; sleep 3"

until [ -s $pidfile ] 
    do sleep $delay
done
terminalpid=$(cat "$pidfile")
rm $pidfile
echo "launched"
while ps -p $terminalpid > /dev/null 2>&1
    do sleep $delay
done
echo "terminated"

можно опустить echo "launched" и echo "terminated" строки, конечно, а также можно измениться delay=0.1 строка к другой задержке между двумя проверками терминального состояния (в секундах) при необходимости в нем, чтобы быть более или менее точными.

Для выполнения другой пользовательской команды в дочернем терминале замените строку

gnome-terminal -x bash -c "echo \$>$pidfile; ls; sleep 3"

со следующим (вставьте команду вместо капитализированного заполнителя!)

gnome-terminal -x bash -c "echo \$>$pidfile; INSERTYOURCOMMANDSHERE"
0
ответ дан 23 May 2017 в 15:39

Специалисты по обслуживанию Ubuntu терминального гномом пакета заметили эту проблему и создали сценарий обертки (в пакете Ubuntu gnome-terminal-3.14.2-0ubuntu3) повторно включить --disable-factory опция; однако, сценарий обертки не работает!

От журнала изменений http://changelogs.ubuntu.com/changelogs/pool/main/g/gnome-terminal/gnome-terminal_3.14.2-0ubuntu3/changelog:

терминал гнома (3.14.2-0ubuntu3) яркий; urgency=medium

  • debian/gnome-terminal: Добавьте сценарий обертки для запуска терминала гнома с другим идентификатором приложения, когда пользователь передаст теперь проигнорированный - опция запрещать-фабрики. Это должно восстановить совместимость со старыми средствами запуска для пользователей, которые обновляют. [...]

Я не могу переместиться по Ubuntu "Панель запуска" (так для открытого исходного кода), но сценарий обертки может быть найден в https://launchpad.net/ubuntu / + архив / основным / + files/gnome-terminal_3.14.2-0ubuntu3.debian.tar.xz (названный gnome-terminal.wrap).

Ошибка то, что gnome-terminal.wrap сценарий ожидает на неправильном дочернем процессе; это должно ожидать на терминальном сервере, не терминальном клиенте. Фиксация должна изменить эти два метода server_appeared и spawn_terminal_server следующим образом:

    def server_appeared(self, con, name, owner):
        # start gnome-terminal now
        gt = Gio.Subprocess.new(['/usr/bin/gnome-terminal.real',
                                 '--app-id', name] +
                                self.args,
                                Gio.SubprocessFlags.NONE)
        # removed a line here: gt.wait_async(...)

    def spawn_terminal_server(self, name):
        ts = Gio.Subprocess.new(['/usr/lib/gnome-terminal/gnome-terminal-server',
                                 '--app-id',
                                 name],
                                Gio.SubprocessFlags.NONE)
        ts.wait_async(None, self.exit_loop, ts)

Можно загрузить фиксированный файл с: https://gist.github.com/ecatmur/00893506a23e828c6688.

Я уведомил специалиста по обслуживанию пакета так, надо надеяться, что это должно быть зафиксировано довольно скоро.


Другой интересный факт: терминал гнома может быть создан с альтернативным позвонившим клиентом gterminal который имеет a --wait опция, которая, кажется, делает точно, что Вы хотите. Однако, к сожалению, Ubuntu не создает или устанавливает его в их терминальном гномом пакете.

3
ответ дан 23 May 2017 в 15:39

В их бесконечной мудрости GNOME devs решил удалить ту опцию. К сожалению, их мудрость не расширялась на также обновление их man страница, которая все еще перечисляет его. Так, это похоже gnome-terminal будет всегда выполняться интервал, к которому будут возвращены фон и родительская сессия оболочки сразу. Для обхождения этого у Вас есть несколько опций:

  1. Просто используйте другой терминал. Я попробовал xterm, rxvt и разделителем GNOME, всем из который работавший как ожидалось.

  2. Используйте некоторые ужасные взломы. gnome-terminal, когда первый показ, запуски /usr/lib/gnome-terminal/gnome-terminal-server. По некоторым причинам это означает, что процесс закончен, как только Вы запустили его. Проиллюстрировать:

    $ gnome-terminal  -x sh -c "ls;sleep 30" 
    [1] 5896
    $ jobs
    [1]+  Done                    gnome-terminal -x sh -c "ls;sleep 30"
    

    Как Вы видите выше после запуска его в фоновом режиме, запущенное задание сразу выходит. Это означает что моя первая мысль о запуске его в фоновом режиме и затем использовании $! проверять, работает ли это все еще, не будет работать. Это означает, что необходимо будет сделать что-то менее изящное как создание файла:

    tmpfile=$(mktemp); gnome-terminal  -x sh -c "ls;sleep 30; rm $tmpfile" 
    while [ -e $tmpfile ] ; do :; done
    

    Команды выше будут i) создавать временный файл (tmpfile=$(mktemp)); ii), запускают терминал гнома, говоря этому удалить $tmpfile по окончании и iii), ничего не делают (:) пока временный файл существует while [ -e $tmpfile ]. Это приведет к терминалу, который ожидает до процесса, выполненного gnome-terminal закончился перед продолжением.

3
ответ дан 23 May 2017 в 15:39

Я использовал более новый терминал гнома, и поведение, которое Вы описали для терминала гнома, кажется, то же для консоли, lxterm, и rxvt (попробовал все 3). Таким образом, так как OP не ответил ни на какие комментарии до сих пор для разъяснения то, что он хочет, я делаю предположение, что OP хочет продолжить использовать родительский терминал, не ожидая дочернего терминала для окончания.

, Который может быть достигнут с gnome-terminal &. Если Вы хотите избежать дочернего терминала, закрываемого, когда родитель выходит, используйте nohup gnome-terminal &. Постараться не видеть вывод ошибок в родительском терминальном использовании gnome-terminal 2> /dev/null & или nohup gnome-terminal 2> /dev/null &.

0
ответ дан 23 May 2017 в 15:39

Для людей в феврале 2017 < t < март 2018, кто приехал в этот сайт через Google, простое решение:

gnome-terminal --disable-factory -e "cmd"

работы и запускает терминал гнома синхронным способом / способом блокирования как ожидалось.

Протестированный под:

  • терминал гнома 3.18.3
Ubuntu 16.04
0
ответ дан 24 May 2017 в 01:39
  • 1
    Ошибочный снимок экрана Сервера произошел как открытый Google Chrome, был не далее вход когда я когда к веб-сайту библиотек. – BJsgoodlife 23 August 2016 в 00:14

Другие вопросы по тегам:

Похожие вопросы: