Único atalho para mover um processo em execução para o segundo plano no bash [duplicado]

0

Eu sei como mover um processo para segundo plano suspendendo-o primeiro, discutindo aqui e here :

  1. Digite Ctrl + Z
  2. Execute %& ou bg

No entanto, eu gostaria de fazer isso sem interromper muito o processo (não tê-lo pausado por muito tempo enquanto eu digito para iniciá-lo novamente). Por exemplo, se estiver tocando áudio e não quiser interferir. Parece que não há nenhuma maneira de realmente movê-lo durante a execução (consulte este e isto ), mas aceitarei com alegria um único atalho que faça as duas operações acima em uma única etapa.

Uma pergunta semelhante está aqui, mas sobre zsh: Como posso fazer Ctrl-Z e bg em um toque de tecla para fazer o processo continuar em segundo plano?

    
por jozxyqk 07.05.2015 / 12:26

1 resposta

0

Os comandos podem certamente ser combinados , mas ativá-los é difícil.

Uma opção é vincular Ctrl-Z no shell para que você possa clicá-lo uma vez para suspender e novamente para bg .

Minha solução é definir um atalho global para executar um script que executa o trabalho. Em primeiro lugar, o PID do shell em execução na janela do terminal ativo é obtido. Em seguida, obtenha o processo em primeiro plano e, finalmente, suspender e retomá-lo . O mesmo funciona se você quiser matá-lo.

Um problema chato é o Konsole do KDE, que tem um único processo para cada janela do terminal. Eu encontrei a resposta aqui, ou pelo menos me apontou na direção certa: link

Aqui está o script:

#!/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

Isso funciona muito bem. Por exemplo,

>>> sleep 100 #press shortcut here

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

No entanto, ele depende do gerenciador de janelas que é capaz de definir atalhos globais e poder obter o terminal ativo e o shell, o que é uma rotunda muito boa. Acho que também pode haver problemas se o ssh estiver em execução, não tenho certeza.

    
por 07.05.2015 / 12:26