Emettere un errore quando si utilizzano variabili shell vuote


22

A volte uso, $PROJECT_HOME/*per eliminare tutti i file nel progetto. Quando la variabile di ambiente PROJECT_HOMEnon è impostata (perché l'ho fatto sue il nuovo utente non ha impostato questa variabile di ambiente), inizia a eliminare tutti i file dalla cartella principale. Questo è apocalittico.

Come posso configurare bashper generare un errore quando uso una variabile d'ambiente non definita nella shell?


5
set -ufarà quello che vuoi.
cuonglm,

puoi farcela come risposta?

2
Naturalmente non avresti inizializzato i tuoi var su stringhe vuote. [ -z "$VAR" ]funziona anche con un non inizializzato VAR. L'inizializzazione era solo per mostrare il comportamento indesiderato: il mio punto è, se i tuoi var vengono mai inizializzati in stringhe vuote, in qualunque modo, e corri rm -r "$PROJECT_HOME"/*erroneamente affidandoti set -u, otterrai il comportamento "apocalittico". IHMO, è meglio prevenire che curare quando si tratta di proteggere l'intero contenuto del computer. set -unon è sicuro.
PSkocik,

3
"È molto lungo"? Non dovresti cercare un modo conveniente per eseguire manualmente operazioni pericolose. Invece, dovresti creare una funzione, un alias o uno script per fare quello che vuoi; in questo caso, creare un alias dal comando suggerito da @ PSkocik sarà sicuro e conveniente.
Kyle Strand,

1
Cosa succede se l'utente imposta PROJECT_HOME=/etc? Il solo controllo di un valore vuoto non è sufficiente per prevenire il cataclisma. Non utilizzare variabili da utenti non attendibili quando si esegue come root.
Barmar,

Risposte:


27

Nella shell POSIX, è possibile utilizzare set -u :

#!/bin/sh

set -u
: "${UNSET_VAR}"

o usando l' espansione dei parametri :

: "${UNSET_VAR?Unset variable}"

Nel tuo caso, dovresti usare :?invece di ?fallire anche su variabili set ma vuote:

rm -rf -- "${PROJECT_HOME:?PROJECT_HOME empty or unset}"/*

17
[ -z "$PROJECT_HOME" ] || rm -r "$PROJECT_HOME"/*

Questo catturerà anche il caso in cui PROJECT_HOME è impostato ma non contiene nulla.

Esempio:

1) Questo eliminerà praticamente tutto ciò che puoi eliminare sul tuo sistema (tranne i file dot all'interno /(di solito non ce ne sono)):

set -u
PROJECT_HOME=
rm -r "$PROJECT_HOME"/*

2) Questo non farà nulla:

PROJECT_HOME=
[ -z "$PROJECT_HOME" ] || rm -r "$PROJECT_HOME"/* 

Rimuovere completamente il progetto a casa e ricrearlo potrebbe essere un'altra opzione (se vuoi sbarazzarti anche dei dotfile):

#no apocalyptic threats in this scenario
rm -r "$PROJECT_HOME"
mkdir "$_" 

1
-zè ok, ma dal momento che $PROJECT_HOMEdovrebbe essere una directory, forse -dsarebbe meglio. [[ -d $PROJECT_HOME ]] && rm -r "$PROJECT_HOME".
Kojiro,

2
Se PROJECT_HOME è impostato su una non directory, si tratta di un errore non irreversibile, probabilmente a causa di un errore di battitura. Il -dcontrollo nasconderebbe quell'errore. Penso che sia meglio se continua rme se ne rmlamenta ad alta voce.
PSkocik,

2
Se PROJECT_HOME è impostato, ma il nome non è una directory, [[ -d $PROJECT_HOME ]] && rm -r "$PROJECT_HOME"non farà nulla, in silenzio. Ma [[ -z $PROJECT_HOME ]] || rm -r "$PROJECT_HOME"eliminerà silenziosamente "$ PROJECT_HOME", anche se si tratta di un file che non è una directory. if [[ -d $PROJECT_HOME ]]; then rm -r "$PROJECT_HOME"; else printf '%s is not a directory\n' "$PROJECT_HOME" >&2; fi
Ricevere

1
Ora "accidentalmente" impostato PROJECT_HOME="/."...
Hagen von Eitzen,

1
@HagenvonEitzen Se PROJECT_HOME è impostato su root, la procedura che svuota PROJECT_HOME svuoterà root. Questo è il comportamento previsto e perfettamente ragionevole. E non hai nemmeno bisogno di quel punto finale.
PSkocik,

0

Un altro modo per farlo:

rm -r "${somevar:-/tmp/or_this_if_somevar_is_empty}"/*

Esistono molte sostituzioni variabili, quella sopra è quando "somevar" è vuoto (e in quel caso tenta di eliminare /tmp/or_this_if_somevar_is_empty/*)


1
Oppure: rm -fr ${ENV_VAR:?suitably caustic message here}/*, ma potrebbe essere ancora la pena di verificare che il valore non mappa alla directory principale, notare che ci sono molti modi per sovvertire semplici test: //, /.., /usr/who/../.., ...
Jonathan Leffler

Sì. Se hai intenzione di utilizzare un'espansione dei parametri, puoi anche utilizzare quello che effettivamente genera un errore
Digital Trauma
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.