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

  1. Введите Ctrl+Z
  2. Запустите либо %& либо bg

Однако я хотел бы сделать это, не прерывая процесс слишком долго (не останавливайте его на века, пока я набираю его снова). Например, если он воспроизводит звук, и я не хочу вмешиваться. Похоже, что нет никакого способа переместить его во время работы (см. Это и это), но я с радостью приму один ярлык, который выполняет обе вышеуказанные операции за один шаг.

Аналогичный вопрос здесь, но о zsh: как я могу сделать Ctrl-Z и bg одним нажатием клавиши, чтобы процесс продолжался в фоновом режиме?

1 ответ1

0

Команды, безусловно, могут быть объединены, но вызвать их сложно.

Одним из вариантов является связывание Ctrl-Z в оболочке, так что вы можете нажать его один раз, чтобы приостановить, и снова bg .

Мое решение состоит в том, чтобы установить глобальный ярлык для запуска скрипта, который выполняет эту работу. Во-первых, PID оболочки, запущенной в окне активного терминала. Затем получите процесс на переднем плане, и, наконец, приостановите и возобновите его. То же самое работает, если вы хотите убить его.

Раздражающей проблемой является консоль KDE, которая имеет отдельный процесс для каждого окна терминала. Я нашел ответ здесь, или, по крайней мере, он указал мне правильное направление: http://wundermark.blogspot.com.au/2013/01/the-sick-and-twisted-world-of.html?m=1

Вот сценарий:

#!/bin/bash

#get the active window
WID=$( xprop -root _NET_ACTIVE_WINDOW | grep -o '0x[0-9a-f]\+' )

#get the parent's process ID (looks like I don't need this as there's only ever one konsole/gnome-terminal process running)
TPID=$( xprop -id $WID _NET_WM_PID | grep -o '[0-9a-f]\+' )

#get the window class, to check what terminal is running
TERM=$( xprop -id $WID WM_CLASS | grep -o 'konsole\|gnome-terminal' ) #change this to match your terminal. only tested with konsole

#quit if a terminal is not active
if [[ -z "$TERM" ]] ; then
    exit -1
fi

#get bash PID for the window, somehow
if [[ "$TERM" == "konsole" ]] ; then
    #this seems really really roundabout, but here goes..
    #for every konsole window (which may have many tabs/sessions)
    for WINDOW in $( qdbus org.kde.konsole /Windows org.freedesktop.DBus.Introspectable.Introspect | grep "node name" | grep -o "[0-9]\+" ) ; do
        #get the "current" session, which I guess is the active tab. seems to work
        SESSION=$( qdbus org.kde.konsole /Windows/$WINDOW org.kde.konsole.Window.currentSession )

        #get the window ID from the environment variables (why is not available via qdbus??)
        KWID=$( qdbus org.kde.konsole /Sessions/$SESSION org.kde.konsole.Session.environment | grep WINDOWID | grep -o "[0-9]\+" )

        #convert it to hex, to match the query at the top
        KWID=$( printf "0x%x\n" $KWID )

        #if this active tab is in the active window, it's the one we want. grab the PID of the shell
        if [[ "$WID" == "$KWID" ]] ; then
            SHELL_PID=$( qdbus org.kde.konsole /Sessions/$SESSION org.kde.konsole.Session.processId )
            break
        fi
    done
else
    ps --ppid $TPID #<- need to figure out which bash PID for the WID, as above for KDE
    echo "only works for KDE atm. sorry"
    exit -1
fi

echo WID=$WID PID=$PID TERM=$TERM SHELL_PID=$SHELL_PID

#find the foreground process
ps -O stat --ppid $SHELL_PID | grep -v PID | while read CHILD ; do
    if [[ -n "$(echo $CHILD | awk '{print $2}' | grep \+)" ]] ; then
        PID=$( echo $CHILD | awk '{print $1}' )
        kill -SIGSTOP $PID
        sleep 0.0001 #??
        kill -SIGCONT $PID
        break
    fi
done

Это работает просто отлично. Например,

>>> sleep 100 #press shortcut here

[1]+  Stopped                 sleep 100
>>> jobs #check it's been restarted
[1]+  Running                 sleep 100 &
>>> 

Однако он полагается на то, что оконный менеджер может устанавливать глобальные ярлыки и получать активный терминал и оболочку, что довольно чертовски окольно. Я думаю, что также могут быть проблемы, если, скажем, ssh работает, не уверен.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .