"Variabilizza" la e commerciale (sfondo di un processo)


9

Voglio sapere se esiste un modo per inserire la e commerciale in una variabile e comunque utilizzarla per inviare un processo in background.

Questo funziona:

BCKGRND=yes
if [ "$BCKGRND" = "yes" ]; then
    sleep 5 &
else
    sleep 5
fi

Ma non sarebbe bello realizzare quelle cinque righe con una sola? Così:

BCKGRND='&'
sleep 5 ${BCKGRND}

Ma questo non funziona. Se BCKGRND non è impostato, funziona, ma quando è impostato viene interpretato come un '&' letterale ed errori.


dopo aver usato la e commerciale finale, echo $!restituisce il PID
noobninja il

Risposte:


9

Non è possibile utilizzare una variabile per mettere in background la chiamata perché l'espansione della variabile si verifica dopo che la riga di comando è stata analizzata per gli operatori di controllo (come &&e &).

Un'altra opzione sarebbe quella di avvolgere le chiamate in una funzione:

mayberunbg() {
  if [ "$BCKGRND" = "yes" ]; then
    "$@" &
  else
    "$@"
  fi
}

... e quindi imposta la variabile secondo necessità:

$ BCKGRND=yes mayberunbg sleep 3
[1] 14137
$
[1]+  Done                    "$@"
# or
$ BCKGRND=yes
$ mayberunbg sleep 3
[1] 14203
$
[1]+  Done                    "$@"
$ BCKGRND=no mayberunbg sleep 3
# 3 seconds later
$

Cosa no ed? +1 comunque, questa è la soluzione più pulita.
Stephen Kitt,

LOL @StephenKitt; ora gli ingranaggi stanno cambiando
Jeff Schaller

Mi è piaciuta la risposta di eval per la sua semplicità, ma il mio attuale comando nel mondo reale che volevo fare da sfondo era troppo complicato con troppe variabili al suo interno per essere a mio agio con eval. @ Jeff-Schaller mi ha dato la risposta che mi ha indicato la direzione in cui sono andato. Invece di una funzione, ho inserito l'intero comando in una variabile, quindi ho usato il suo stile if per eseguire il comando con o senza &.
BrowncoatOkie

11

Puoi capovolgere le cose e variare il "primo piano":

FOREGROUND=fg
sleep 5 & ${FOREGROUND}

Impostato FOREGROUNDsu trueo vuoto per eseguire il processo in background. (L'impostazione FOREGROUNDper truel'esecuzione in background è certamente confusa! I nomi delle variabili appropriate vengono lasciati come esercizio per il lettore.)


4
è carino ma non funzionerà in una shell senza controllo del lavoro (cioè qualsiasi script a meno che non sia set -mstato usato).
mosvy,

9

Probabilmente dovresti usare eval:

eval "sleep 5" "$BCKGRND"

evalfa sì che la shell rivaluti gli argomenti forniti. Un letterale &verrebbe quindi interpretato come &alla fine di un comando e non come argomento per il comando, mettendo il comando in secondo piano.


2
Una risposta contenente evaldovrebbe contenere un avviso, che deve essere maneggiato con cura. Vedi ad esempio questa risposta .
Ralf

Non capisco quale sia il problema con la "$BCKGRND"valutazione di un argomento vuoto.
mosvy,

2
@Ralf assolutamente irrilevante in questo caso . Non c'è niente di speciale in eval: puoi eseguire comandi tramite espansioni aritmetiche, ad esempio. Forse dovrebbe esserci un tale avvertimento contro l'uso di bash (o qualsiasi shell simile) ;-)
mosvy

1
@Kusalananda evalunirà le sue argomentazioni con gli spazi prima di fare l'attuale valutazione. Provare per credere: eval printf "'{%s}\n'" foo "" "" "". eval foo "" "" "" ""è completamente simile a eval foo, qualunque cosa IFSo altra cosa sia.
mosvy,

1
Il comando da valutare dovrebbe essere tra virgolette doppie se contiene caratteri speciali, ad es eval 'sleep $TIMEOUT' "$BACKGROUND". Altrimenti potresti ottenere doppie espansioni se la variabile si espande in un'altra variabile o contiene caratteri speciali. Inoltre, la quotazione nidificata può diventare complicata.
Barmar il
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.