Come avviare uno script con un ambiente pulito?


15

Ho provato quanto segue ma non sembra funzionare:

$ cat script.sh
#!/bin/env -i /bin/sh

/bin/env
$ script.sh
/bin/env: invalid option -- ' '
Try `/bin/env --help' for more information.

Trovate domande simili ma non mostra come fare da shebang: unix.stackexchange.com/questions/48994/…
balki

5
Non puoi farlo da Shebang. Lo shebang può accettare solo un argomento.
jordanm,

Risposte:


7

Il motivo per cui non funziona è perché vede -i /bin/shcome un unico argomento env. Di solito questo sarebbe 2 argomenti -ie /bin/sh. Questa è solo una limitazione dello shebang. Assolutamente no.


Tuttavia è ancora possibile eseguire questa attività, solo in un modo diverso.

Se si desidera che questa attività venga eseguita dallo script stesso e non si debba fare qualcosa del genere env -i script.sh, è possibile ripetere l'esecuzione dello script.

#!/bin/sh
[ -z "$CLEANED" ] && exec /bin/env -i CLEANED=1 /bin/sh "$0" "$@"

Ciò causerà la riesecuzione automatica dello script se la CLEANEDvariabile di ambiente non è impostata. Quindi su re-exec, imposta la variabile per assicurarsi che non entri in un ciclo.


envdai coreutils GNU ora hanno un'opzione -Sper risolvere i problemi simili a questo ma non esattamente lo stesso. Per esempio #!/usr/bin/env -S perl -T.
Weijun Zhou,

Ho appena provato. Funziona anche per la domanda originale. Basta usare #!/usr/bin/env -S -i /bin/sh. Essere consapevoli dei problemi di portabilità.
Weijun Zhou,

3

Esegui il tuo script con env -i:

env -i script.sh

E la sceneggiatura come al solito:

#!/bin/sh
# ... your code here

Se intendi correre con un ambiente pulito senza dirlo esplicitamente quando corri. Eduardo Ivanec dà alcune idee in questa risposta , puoi chiamare ricorsivamente il tuo script con execquando l'ambiente non è pulito (ad esempio $ HOME è definito):

[ "$HOME" != "" ] && exec -c $0

Bello. Non fare env -i bash come ho fatto io e poi mi chiedo perché le tue variabili env siano ancora impostate (ovviamente bash risorse .bashrc e amici 8)
Neil McGill

2

Con bash, puoi farlo in questo modo:

#!/usr/bin/bash

set -e
set -u

[ -v HOME ] && exec -c "$0" "$@"

# continue with the rest of the script
# e.g. print the cleaned environment:
export

I comandi set -ee set -unon sono strettamente necessari, ma li includo per dimostrare che questo approccio non si basa sull'accesso a variabili non impostate (come ad esempio [ "$HOME" != "" ]farebbe) ed è compatibile con set -eun'impostazione.

Il test della HOMEvariabile dovrebbe essere sicuro perché bash esegue gli script in modalità non interattiva, vale a dire che i file di configurazione come ~/.bashrc(dove è possibile impostare le variabili di ambiente) non provengono durante l'avvio.

Esempio di output:

declare -x OLDPWD
declare -x PWD="/home/juser"
declare -x SHLVL="1"

0

$ cat script.sh

#!/bin/env -i /bin/sh

Purtroppo non funzionerà in questo modo - Linux considera -i /bin/shun argomento a cui passare env(vedi Shebang ).


0

La limitazione shebang di Linux a 2 argomenti (interpeter + singolo argomento) è annotata nella maggior parte delle risposte, ma dire che ciò non può essere fatto è errato - devi solo passare a un interprete che può fare qualcosa di utile con un singolo argomento:

#!/usr/bin/perl -we%ENV=();exec "/bin/sh " . join " ", map "'$_'", @ARGV;
# your sh script here

Ciò che fa ciò è invocare perlcon uno script one-liner ( -e) che cancella %ENV(più economico di env -i) e invoca exec /bin/sh, citando correttamente gli argomenti. È perlpossibile aggiungere ulteriore logica, se necessario (anche se non molto su Linux poiché sei limitato ai BINPRM_BUF_SIZEcaratteri, che è probabilmente 128)

Purtroppo, questo è specifico di Linux, non funzionerà su un sistema che consente molteplici argomenti shebang: - /

perlelabora questa stringa come un singolo argomento, quindi non è citata sopra come faresti normalmente perl -e ...dalla riga di comando (se dovessi aggiungere virgolette queste vengono conservate, perl vede solo una stringa letterale, con avvisi su di essa si lamenterà di un inutile costante).

Nota anche che c'è un leggero cambiamento nel comportamento quando usato in questo modo, @ARGVnormalmente contiene solo gli argomenti e $0contiene lo script, ma con questo shebang $ARGV[0]è il nome dello script (ed $0è -e) che lo rende un po 'più facile.

Puoi anche risolverlo con un interprete che "rielabora" la sua riga di comando (senza un -cargomento in più) che l'antica AT&T ksh93fa:

#!/bin/ksh /usr/bin/env -i /bin/sh

anche se forse kshnon è così comune al giorno d'oggi ;-)

( bashha una funzione simile con --wordexp, ma è "non documentato" nelle versioni in cui funziona e non è abilitato in fase di compilazione nelle versioni in cui è documentato: - / Inoltre non può essere utilizzato per questo poiché ha bisogno di due argomenti. ..)

Inoltre, effettivamente una variazione sulle risposte di @Patrick e @ maxschlepzig:

#!/bin/bash
[ "$_" != bash ] && exec -c -a "bash" /bin/bash "$0" "$@"
# your script here

Invece di usare una nuova variabile, questa utilizza la speciale " _" variabile, se non è impostata esattamente su "bash", quindi sostituire lo script con l' executilizzo -adi make ARGV[0](e quindi $_) solo "bash" e l'utilizzo -cper cancellare l'ambiente.

In alternativa, se è accettabile pulire l'ambiente all'inizio dello script (solo bash):

#!/bin/sh
unset $(compgen -e)
# your script here

Questo usa compgen(helper di completamento) per elencare i nomi di tutte le variabili d'ambiente esportate e le usa unsetin una volta sola.

Vedi anche Argomenti multipli in shebang per maggiori dettagli sul problema generale del comportamento di shebang.

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.