Shell Script mktemp, qual è il metodo migliore per creare pipe denominate temporaneamente?


30

Sono consapevole che è meglio creare file temporanei con mktemp, ma per quanto riguarda le pipe denominate?

Preferisco che le cose siano il più possibile conformi a POSIX, ma solo Linux è accettabile. Evitare i bashismi è il mio unico criterio difficile, mentre scrivo dash.

Risposte:


41
tmppipe=$(mktemp -u)
mkfifo -m 600 "$tmppipe"

A differenza della normale creazione di file, che è soggetta a dirottamento da un file esistente o da un collegamento simbolico, la creazione di una pipe con il nome mkfifoo la funzione sottostante crea un nuovo file nel posto specificato o fallisce. Qualcosa di simile : >foonon è sicuro perché se l'attaccante è in grado di prevedere l'output di mktempallora, l'attaccante può creare il file di destinazione per se stesso. Ma mkfifo foofallirebbe in un simile scenario.

Se hai bisogno della completa portabilità POSIX, mkfifo -m 600 /tmp/myfifoè sicuro contro il dirottamento ma incline a una negazione del servizio; senza l'accesso a un potente generatore di nomi di file casuali, è necessario gestire i tentativi di nuovo tentativo.

Se non ti interessano i sottili problemi di sicurezza relativi ai file temporanei, puoi seguire una semplice regola: creare una directory privata e tenere tutto lì dentro.

tmpdir=
cleanup () {
  if [ -n "$tmpdir" ] ; then rm -rf "$tmpdir"; fi
  if [ -n "$1" ]; then kill -$1 $$; fi
}
tmpdir=$(mktemp -d)
trap 'cleanup' EXIT
trap 'cleanup HUP' HUP
trap 'cleanup TERM' TERM
trap 'cleanup INT' INT
mkfifo "$tmpdir/pipe"

In realtà l'ho già scelto come soluzione ieri, stavo aspettando di vedere se qualcuno lo aveva pubblicato o uno migliore. Ho anche sentito che la dir era la strada da percorrere, nel mio caso. Indipendentemente da ciò ... Grazie per l'aiuto, lo apprezzo.
JM Becker,

1
Il comando trap non dovrebbe essere trap "rm -rf '$tempdir'" EXIT HUP INT TERM? Trap può fare la propria espansione variabile?
Sei

@Six Il comando si espanderebbe $tempdirnel momento in cui trapviene valutato il comando, non nel momento in cui viene attivata la trap. In questo caso, non fa alcuna differenza, tranne che il tuo codice si rompe orribilmente se il valore di tempdircontiene una singola virgoletta, mentre il mio codice funziona sempre.
Gilles 'SO- smetti di essere malvagio'

@Gilles Questa è una bella caratteristica. Avevo provato il tuo singolo esempio di citazione senza fortuna, quindi pensavo che trap non fosse in grado di valutare le variabili in fase di esecuzione. Si è scoperto che il mio è $tempdirstato dichiarato localmente e deve essere definito a livello globale affinché Trap possa accedervi. Ha senso adesso ...
Sei

1
@Gilles ... fintanto che il $tempdir valore non cambia neanche, il che è accettabile praticamente per tutti gli scopi.
Fai

3

Un'alternativa più sicura consiste nell'utilizzare mktempper creare una directory in modo sicuro, quindi inserire la propria pipe denominata all'interno di quella directory, fare una cosa rm -R $dirper sbarazzarsene alla fine.


Ho scelto di creare il FIFO in una mktempdirectory, dato che era davvero l'unica risposta accettabile, nel caso non l'avessi notato, @Gilles ha già pubblicato questa risposta in modo approfondito.
JM Becker,

2

Utilizzare l'opzione "dry-run":

mkfifo $(mktemp -ut pipe.XXX)

1
Secondo le pagine man, l'uso -udell'opzione "non è incoraggiato".
dogbane,

@dogbane Così è l'uso di -t, ma fintanto che funziona in modo affidabile, ci andrei.
polemon

scusa, dove dice che -tè scoraggiato?
dogbane,

2
@dogbane Se fosse in qualche modo critico, farei una piccola applicazione C, chiamando la mkstemp()funzione ( linux.die.net/man/3/mkstemp ). L' -tinterruttore non è scoraggiato, lo è -p, il mio male.
polemon

1

È possibile utilizzare mktempper creare un file temporaneo, quindi eliminarlo e creare una pipa denominata con lo stesso nome.

Per esempio:

TMPPIPE=$(mktemp -t pipe.XXX) && {
    rm -f $TMPPIPE
    mkfifo $TMPPIPE
}

L'eliminazione di $TMPPIPEprima mkfifoevita il problema "non sicuro" associato TMPPIPE=`mktemp -u` ; mkfifo $TMPPIPE?
JM Becker,

1
@TechZilla mkfifoè in realtà sicuro, a differenza della normale creazione di file dalla shell. In caso contrario, la creazione di un file e la sua eliminazione non sarebbe affatto utile (in effetti faciliterebbe notevolmente il lavoro dell'attaccante non richiedendogli di indovinare il nome del file). Quindi la risposta di dogbane funziona, ma la creazione di file intermedi è una complicazione inutile.
Gilles 'SO- smetti di essere malvagio' il

1
@Gilles, sai a che proposito la mktemppagina man ha chiamato l' -uopzione 'non sicuro'?
JM Becker,

@dogbane, ho votato a favore della tua risposta e i tuoi commenti che ho ritenuto solidi. Anche se l'ho già completato ieri ... stavo solo aspettando di vedere quando qualcuno ha pubblicato la mia soluzione o, si spera, una migliore. Quindi, anche se ho usato, mktemp -dhai comunque ottenuto alcuni punti per il tuo contributo. Grazie per tutto il tuo aiuto, lo apprezzo davvero!
JM Becker,

1
@TechZilla mktemp -unon è sicuro quando si crea un file regolare, perché fornisce la protezione contro la negazione del servizio (se il nome che genera è sufficientemente imprevedibile) ma non impedisce a un utente malintenzionato di creare il file sotto il naso del programma. La creazione di un file FIFO invece di un normale è un caso d'uso raro che la pagina man non risolve.
Gilles 'SO- smetti di essere malvagio' il

0

Usa mkfifoo mknodin Unix, dove due processi separati possono accedere alla pipe per nome: un processo può aprirlo come lettore e l'altro come scrittore.

mkfifo my_pipe
gzip -9 -c < my_pipe > out.gz
cat file > my_pipe

La pipe denominata può essere eliminata come qualsiasi altro file:

rm my_pipe

mkfifo --mode=0666 /tmp/namedPipe
gzip --stdout -d file.gz > /tmp/namedPipe

NamedPipe può essere utilizzato un normale file per la sola lettura.

http://www.linuxjournal.com/article/2156


2
Sono pienamente consapevole delle named pipe e mkfifo. Non affronta la mia domanda sulle pipe temporanee con nome, più di quanto non mkdirriguarderebbe la creazione di directory temporanee.
JM Becker,

2
In che modo mktemprisolve i problemi che risolvono per creare in modo sicuro una pipe denominata?
Camh,

1
oh ok, la cosa migliore è crearli in / tmp, sono file temporanei per definizione e si cancelleranno una volta riavviato il sistema. O meglio ancora, avere una funzione shell che creerà il namedpipe dal mktemprisultato stesso (ovviamente cancellando prima il file temporaneo e quindi eseguendolo mkfifosullo stesso). mktemppuò anche essere usato per creare una directory temporanea, provare con -t -dswitch.
Nikhil Mulley,
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.