Eseguire parti di .bashrc in modo asincrono


8

Ho alcune esportazioni e altre cose che richiedono l'esecuzione di un altro programma (per ottenere percorsi o altro) e richiedono un periodo di tempo non banale, il che significa che il mio tempo di avvio di bash è dell'ordine di 5 secondi.

Prima di uscire e aggiungere un po 'di cache di base nel mio .bashrc, c'è un modo in cui posso eseguire qualcosa in modo asincrono che mi permetterà di esportare variabili nella mia shell in esecuzione?

(Quindi, questo in realtà non si limita a .bashrc, ma bash in generale.)

Risposte:


2

Molto dipende da quando questi programmi devono essere eseguiti e da quando hai bisogno dei loro risultati. Se non importa quando corrono (ovvero, i loro risultati non variano con il tempo), allora potrebbe essere meglio farli funzionare dal tuo ~/.profileo ~/.bash_profile(cioè, quando accedi) piuttosto che dal tuo ~/.bashrc.

Se hai bisogno dei loro risultati, ma non puoi aspettare i 5 secondi necessari per farli funzionare, cosa farai per i primi 5 secondi che la tua shell è attiva? Non è possibile eseguire comandi che dipendono dagli output di tali programmi, poiché i risultati non saranno ancora disponibili.

Penso che se descrivi più in dettaglio esattamente quali sono i requisiti, potremmo essere in grado di darti risposte migliori.

Detto questo, potresti lanciare i tuoi programmi in background come suggerito da Dennis Williamson, e farli scrivere i loro risultati su alcuni file nella tua home directory. Quindi è possibile impostare la variabile bash PROMPT_COMMANDin modo che generi tali file, cosa che bash farebbe prima di ogni visualizzazione di PS1.

Ad esempio, supponiamo che il tuo programma in background scriva export ans=42nel file ~/answeral termine. Nel tuo ~/.bashrc, metti

PROMPT_COMMAND=". ~/answer"

Quindi, ogni volta che viene visualizzata la shell PS1, verrà originariamente sorgente ~/answere il tuo ambiente alla fine (ad es. 5 secondi dopo l'avvio) conterrà la variabile anscon il valore 42.

Ovviamente, i primi 5 secondi dopo l'avvio della shell, ~/answerconterranno i valori dell'ultima volta che hai avviato una shell, quindi dovresti decidere se è importante (e come reimpostare quel file se necessario).


1

Potresti pensare di bilanciare il carico di lavoro tra il tuo profilo, che viene eseguito una volta, e il tuo file bashrc, che viene eseguito ogni volta che avvii (un bash interattivo). Mantengo il mio bashrc minimo - quindi mi avvio velocemente. Il mio profilo non è troppo male - è complesso, ma sicuramente non richiede 5 secondi.


Buoni consigli. Sfortunatamente, nel mio caso specifico, questo non aiuterà su Mac OSX, poiché lì le shell sono sempre caricate come shell di login che porta sempre alla fonte profile, ogni volta che viene creato un nuovo terminale. Grazie Apple.
Kamafeather,

Hmmm; è qualcosa che trovo utile: apro un nuovo terminale sul mio Mac e esegue il mio profilo per me. È quello che voglio. Quando eseguo una shell all'interno di quella finestra, il minimo .bashrc mantiene quell'avvio veloce. Mi infastidisce all'infinito quando un terminale viene spuntato con una shell e non esegue il mio profilo. Ognuno per sé e YMMV, come si suol dire.
Jonathan Leffler,

Fortunatamente tu :) - Da quello che ho letto, Apple è un'implementazione errata del modello bash. I profilefile dovrebbero essere eseguiti solo una volta (su OSX dovrebbe essere al login dell'utente, suppongo), mentre ogni nuovo terminale dovrebbe essere eseguito .bashrc. Ma dal momento che Apple è passata a bash non stanno facendo nessuno di loro; eseguendo sempre una login-shell` per ogni nuovo terminale e mai eseguendo il file .bashrc. Potrebbe essere adatto a casi d'uso in cui non esiste una configurazione intensiva tramite script di shell, ma è sostanzialmente rotto; rompe le aspettative create nei documenti, nella sezione * INVOCATION di man bash.
Kamafeather,

1

Non sono a conoscenza di alcun modo che possa impostare le variabili in background. Tuttavia, è possibile eseguire script in background in modo che vengano eseguiti in parallelo, anziché in sequenza, mentre catturano il loro output. Questo può accelerare l'esecuzione. È possibile utilizzare i descrittori di file 3-9 con questo metodo per un totale di 7 processi paralleli.

Per essere chiari, tutti i comandi eseguiti devono terminare prima di generare la shell interattiva al fine di utilizzare il loro output nell'impostazione delle variabili.

Questa soluzione consente semplicemente l'esecuzione di parti dello script in parallelo al resto dello script (in questo caso, il .bashrc)

function copget { read -u $1; echo "$REPLY"; }

coproc DATE { date; }
exec 3<&${DATE[0]}

coproc UNAME { uname; }
exec 4<&${UNAME[0]}

var1=$(copget 3)
exec 3>&-

var2=$(copget 4)
exec 4>&-

ewindisch, potresti aggiungere qualche commento a destra delle execdichiarazioni? Non riesco mai a ricordare come usare correttamente (e in sicurezza !) Le forme <&e >&del reindirizzamento.
Zearin,

0

È possibile utilizzare una e commerciale per eseguire un processo in background.

some_program &

Tuttavia, il programma non sarà in grado di influenzare direttamente l'ambiente della shell che lo ha avviato.

Non dovresti avere processi di lunga durata nei file di avvio.

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.