Visualizzazione di stdout di un processo in background in una posizione specifica del terminale


8

Ho un comando che eseguo ogni volta che viene aperto un nuovo terminale o viene effettuato un nuovo accesso.

Questo programma produce output (colorato) che dovrebbe essere posizionato prima del prompt dei comandi. Potrebbero essere necessari alcuni secondi, il che mi impedirà di utilizzare il terminale fino a quel momento (a meno che non venga eseguito in background).

Dato che zsh ha alcuni modi avanzati di ridisegnare il terminale senza ostruire il testo esistente, vorrei sapere come posso eseguire questo comando in un modo che non devo aspettare che finisca prima di poter usare il terminale ma quello una volta terminato, stampa l'output come se in primo luogo non fosse in background.

In pratica vorrei qualcosa che potesse fare:

Command output:
... (running on background)
me@computer: somecommand
me@computer: someothercommand

e una volta terminato il comando otterrei:

Command output:
 * Output foo
 * Multiple lines bar
 * and some yada
me@computer: somecommand
me@computer: someothercommand

Ho provato a mettere il processo in background all'avvio ma poi non visualizza l'output in modo pulito. Ottengo qualcosa del tipo:

Command output:
[2] 32207
me@computer: somecommand
me@computer: someother * Output foo
 * Multiple lines bar
 * and some yada
[2]  + done       command
me@computer: someothercommand

Quindi è possibile? Se non con zsh c'è qualche soluzione là fuori che potrebbe farlo?

Qualsiasi suggerimento o informazione è il benvenuto.


Non è possibile se il programma è in esecuzione direttamente nel terminale, perché c'è solo una posizione del cursore e zsh e il programma sarebbe in competizione per esso. Si potrebbe fare qualcosa con zpty: far eseguire il comando in un terminale creato da zsh, con la sua uscita inoltrata al terminale reale sotto il controllo di zsh.
Gilles 'SO- smetti di essere malvagio'

@Gilles Potresti approfondire l'uso di zpty? Sono consapevole che non puoi avere due programmi che scrivono sullo stesso terminale senza una sorta di competizione sul cursore. La mia domanda viene dal fatto che zsh riscrive già il prompt in alcune configurazioni. Ovviamente questo programma dovrebbe scrivere su un buffer temporaneo in memoria che verrebbe "stampato" nella posizione specifica una volta terminato il comando. Tutti questi ultimi sotto il controllo di zsh.
unode

@Gilles: forse vale davvero una risposta?
Stéphane Gimenez,

@ StéphaneGimenez Certo, lo è. Non so come farlo senza alcune ricerche, e non ho tempo per questa ricerca in questo momento.
Gilles 'SO- smetti di essere malvagio' il

Un'idea sarebbe quella di farlo screencon uno script di avvio che divide lo schermo ed esegue il long runner nella parte superiore e la normale riga di comando nella parte inferiore.
Vasquez,

Risposte:


5

Questa è una soluzione semplice se si desidera accettare l'output appena sopra la riga del prompt corrente.

TRAPUSR1 () { zle -I; unfunction TRAPUSR1 }  # invalidate prompt on signal USR1

bufferout () {
    local buffer
    while read -r line; do                   # buffer lines from stdin
        buffer="$buffer$line\n"
    done
    print -rn -- $terminfo[dl1]              # delete current line
    print -rn -- $terminfo[cr]               # move cursor to BOL
    printf "$buffer"                         # print buffer
    kill -USR1 $$                            # send USR1 when we're done
}

unsetopt monitor                             # don't monitor this job
./testout |& bufferout & disown              # bg and disown to suppress notification
setopt monitor                               # restore job monitoring

Al termine del lavoro, il prompt e il buffer di input correnti verranno rimossi stdoute stderrverranno stampati tutti i comandi completi.

È possibile ottenere molto più di fantasia di quella con il zsh/cursesmodulo, ma dubito che avrebbe offerto un sufficiente vantaggio significativo da meritare lo sforzo.


Questo funziona Ma quanto sarebbe difficile impedire alla shell di stampare il processo pid quando viene inviato in background e il messaggio "completato" al completamento? (Intendo disattivare temporaneamente quella funzione). Inoltre, prima di mettere l'output sul terminale, quanto sarebbe difficile cancellare la o le righe di prompt esistenti?
unode

Penso che potrei avere qualche altro prompt di riscrittura che si scontra con la cancellazione del prompt iniziale. Il mio non scompare al termine del comando. Ottengo anche i PID dei processi quando vengono inviati in background ma la riga "done" è sparita. In ogni caso, accetto la tua risposta perché è abbastanza vicino a quello che avevo in mente. Grazie.
unode

Sto usando xterm e ho il modulo VCS abilitato e alcune altre personalizzazioni al prompt. Non ci ho provato ma sono abbastanza sicuro che sia collegato a questo. Qualche tempo fa ho provato a utilizzare il notificatore di modalità vi simile a questo ( stackoverflow.com/a/3791786/125801 ) e quando attivo ho perso parte del mio comportamento prompt personalizzato. Non è un grosso problema, al momento sono contento della soluzione. Proverò a ripulire il mio prompt uno di questi giorni e verificherò se i PID vengono ancora visualizzati.
Unode,

Zsh-4.3.10, dopo aver disabilitato praticamente ogni personalizzazione, ora non ricevo più il prompt (ovvero è stato rimosso correttamente) ma ho ancora i PID dei processi in background, come [1] 27911 27912in una singola riga e come prima riga nella terminale.
Unode,

Posso ripetere la votazione? :) Adesso è perfetto! Grazie mille.
unode,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.