while-loop não parece se lembrar da atualização de variável - nenhuma tubulação envolvida

2

Estou executando o LMDE 2 ('Betsy') com a área de trabalho padrão do Mate e tenho o seguinte script:

#!/bin/bash
# This script starts a specified terminal-binary in "Always on Top"-mode
# The assumption is, that 'wmctrl -l' sorts windows with the 
# in such a way, that the more recently a window has been created, 
# the lower it will be on the list ( compared to windows with the 
# same title).
#
# This is my assumption based on a short observation. The window 
# ids are probably given out in ascending hex numbers
# 
# Note: Using the pid will not help, since all terminals seem to
# be having the same pid
term_title_def='Terminal'
term_title='Terminal_top'
term_cmd="mate-terminal --title=$term_title"

# start terminal, wait for window  to appear and get id of most recently created window
# NOTE: a possible wrap-around of window ids has not been considered here!
eval $term_cmd
win_id=''
while [[ -z $win_id ]]; do
    win_id=$(wmctrl -l | grep "[[:blank:]]$term_title\$" | tail -n 1 | awk '{ print $1 }')
done

# DEBUG
touch /tmp/$win_id

# rename, set as "Always on top"
wmctrl -ir $win_id -T "$term_title_def"
wmctrl -ir $win_id -b add,above
wmctrl -ia $win_id

De alguma forma, o script nunca sai do loop while (verificado com ps aufx ) na primeira execução de um link do painel MATE após a reinicialização. As chamadas subseqüentes funcionam como esperado, ou seja, o link faz o que eu quero (veja os comentários do script acima).

Então, de alguma forma, logo após iniciar o MATE, win_id não é expandido corretamente em while -test, suponho (?). Ou algo assim.

Por que isso acontece?
Agora vou tentar algo como while true; do stuff; break; done e espero que funcione ...

UPDATE:
Substituindo o while -loop acima pelo seguinte

while true; do
    win_id=$(wmctrl -l | grep "[[:blank:]]$term_title\$" | tail -n 1 | awk '{ print $1 }')
    [[ $win_id ]] && break
done

não mudou nada. O script ainda está preso em um loop infinito ...

    
por polynomial_donut 08.09.2015 / 08:32

2 respostas

0

Não vejo como isso funcione. Quando você corre

eval $term_cmd 

você abrirá uma janela de terminal e o script não fará mais nada até que você a feche. O que você precisa é:

$term_cmd &

Execute-o em segundo plano (e não use eval , não é necessário). Então, você também não precisa selecionar a última linha da saída de wmctrl . Você está definindo o título do terminal, então defina-o como algo único e grep que:

#!/bin/bash
# This script starts a specified terminal-binary in "Always on Top"-mode
# The assumption is, that 'wmctrl -l' sorts windows with the 
# in such a way, that the more recently a window has been created, 
# the lower it will be on the list ( compared to windows with the 
# same title).
#
# This is my assumption based on a short observation. The window 
# ids are probably given out in ascending hex numbers
# 
# Note: Using the pid will not help, since all terminals seem to
# be having the same pid
term_title_def='Terminal'
term_title="Terminal_top_$$" ## Use the script's PID for a unique title
term_cmd="mate-terminal --title=$term_title"

## Start terminal. No need to wait, the loop will run until
## the terminal has been opened
$term_cmd &

win_id=''

while [[ -z "$win_id" ]]; do
    ## No need for '[[:blank:]]' and \$, you are using a unique title,
    ## keep the regex general. 
    win_id=$(wmctrl -l | grep "$term_title" | awk '{ print $1 }')
done
# DEBUG
touch /tmp/$win_id

# rename, set as "Always on top"
wmctrl -ir $win_id -T "$term_title_def"
wmctrl -ir $win_id -b add,above
wmctrl -ia $win_id
    
por 08.09.2015 / 14:38
-2

O loop while é executado em um subshell, portanto, qualquer modificação feita na variável no subshell não é relatada no shell pai: link

Para a segunda edição do meu lado eu tenho:

$ while true; do toto=plop; echo $toto; [[ $toto ]] && break ; done 
plop

Então eu acho que você tem um problema real com a definição de $win_id dentro do loop.

    
por 08.09.2015 / 11:39