Alla shell è permesso ottimizzare comandi di terminazione inutili?


27

Se a una shell viene chiesto di eseguire un comando probabilmente inutile ( o parzialmente inutile ) noto per essere terminato, ad esempio cat hugeregularfile.txt > /dev/null, può saltare l'esecuzione di quel comando ( o eseguire un equivalente più economico, diciamo, touch -a hugeregularfile.txt )?

Più in generale, la shell è simile ai compilatori C in quanto può eseguire qualsiasi trasformazione sul codice sorgente, purché il comportamento osservabile esternamente sia come se la macchina astratta lo avesse valutato?

MODIFICARE

Nota Bene: La mia domanda, come originariamente posta, aveva un titolo che chiedeva se alla shell fosse permesso fare queste ottimizzazioni, non se dovesse o anche se esistessero implementazioni che possono farle. Sono interessato alla teoria più che alla pratica, sebbene entrambi siano i benvenuti.


No, la shell non è intelligente come i compilatori moderni. In effetti, è piuttosto stupido. Non ottimizzerebbe alcun codice inutile.
Devnull

12
Indovinare quale sia l'intenzione dell'utente non è qualcosa che la shell dovrebbe fare. L'utente potrebbe provare a fare quasi tutto con quel comando, ottimizzarlo sarebbe la cosa sbagliata da fare, anche se fosse possibile.
Chris Down,

1
Non importa dire che se il file fosse un dispositivo, allora catfarebbe una grande differenza. La shell può sapere che il file è un dispositivo, ma non è necessario che sia affidabile.
yo

3
I compilatori C @StephaneChazelas non devono "chiedere il permesso a qualcuno" per ottimizzare i loro programmi compilati; Esiste una regola as-if nello standard C che consente loro di farlo. Lo standard POSIX sembra aver standardizzato almeno una shell ( pubs.opengroup.org/onlinepubs/009695399/utilities/… ), nonché numerose altre utilità ( pubs.opengroup.org/onlinepubs/009604499/utilities/wc.html per wc, per esempio). Ma per quanto ne so POSIX non prende posizione sull'ottimizzazione della shell; O lo fa?
Iwillnotexist Idonotexist

2
L'ottimizzazione sta migliorando le prestazioni con le scorciatoie senza influire sulla funzionalità. Finché la funzionalità è garantita, non riesco a vedere l'obiezione POSIX. Tuttavia, la tua ottimizzazione proposta romperebbe le specifiche del gatto . Ci sono diciture specifiche nelle specifiche POSIX che sono lì per adattarsi al tipo di ottimizzazione effettuata da ksh. Come se non dicessero un processo separato ma un ambiente subshell per consentire ottimizzazioni di risparmio fork.
Stéphane Chazelas,

Risposte:


26

No, sarebbe una cattiva idea.

cat hugeregularfile.txt > /dev/nulle touch -a hugeregularfile.txtnon sono gli stessi. catleggerà l'intero file, anche se si reindirizza l'output a /dev/null. E leggere l'intero file potrebbe essere esattamente quello che vuoi. Ad esempio, per memorizzarlo nella cache in modo che le letture successive siano significativamente più veloci. La shell non può conoscere la tua intenzione.

Allo stesso modo, un compilatore C non ottimizzerà mai la lettura di un file, anche se non guardi le cose che leggi.


2
@Iwillnotexist: ogni comando utile (tranne discutibilmente truee false) ha potenziali effetti collaterali e gli effetti collaterali sono quasi sempre il punto di invocare il comando. La shell non è stata in grado di conoscere in anticipo tali effetti collaterali (per programmi esterni come cat) senza risolvere il problema dell'Halting. Quindi giustamente non ci prova e presume che tu intendessi ciò che hai detto.
cHao,

5
@IwillnotexistIdonotexist No, la shell non può vedere tutto ciò che sta per accadere. Non ne ha idea cat. In effetti, catpotrebbe fare qualsiasi cosa, dalla formattazione del disco rigido al download di Internet.
scai

5
"Unix non è stato progettato per impedire ai suoi utenti di fare cose stupide, in quanto ciò impedirebbe loro anche di fare cose intelligenti". - Doug Gwyn
Agi Hammerthief

7
@cHao E anche truee falseimpostato $?.
Kyle Strand

3
Come sottolineato da @scai sopra, gli eseguibili non sono come le parole chiave del linguaggio: cate /dev/nullhanno significati tipici ma non sono garantiti per comportarsi in quel modo. Per eseguire ottimizzazioni garantendo al contempo nessuna modifica al comportamento previsto, l'ottimizzazione potrebbe essere consentita solo con costrutti implementati all'interno della shell stessa e non con elementi trovati nell'ambiente di esecuzione ... non importa quanto intuitivi possano apparire i loro nomi.
Andybuckley,

20

No, poiché /dev/nullè solo un nome, che potrebbe essere utilizzato per qualsiasi altro dispositivo o per un file diverso da quello che "normalmente" è un sink di dati.

Quindi una shell (o qualsiasi altro programma) non ha idea, in base al nome, se il file su cui sta scrivendo stia facendo qualcosa di "reale" con i dati. Non ci sono AFAIK, inoltre nessun sistema può chiamare il programma shell per determinare che, ad esempio, il descrittore di file non stia effettivamente facendo nulla.

Il confronto con l'ottimizzazione del codice assente in un programma C non funziona, poiché una shell non ha la panoramica totale che un compilatore C ha su un pezzo di codice sorgente. Una shell non sa abbastanza /dev/nullper ottimizzare il tuo esempio, più come un compilatore C non conosce abbastanza il codice in una chiamata di funzione a cui si collega dinamicamente, per non effettuare la chiamata.


4
A quanto pare, ksh93 tratterà in modo /dev/nullspeciale, a volte. Un builtin a cui è diretto il suo stdout /dev/null, ad esempio echo foo >/dev/null, non comporterà alcuna scrittura /dev/null. Non fa nulla di speciale se sta invocando un comando non incorporato (come cat file >/dev/null).
Mark Plotnick,

In realtà, catpotrebbe anche essere qualcos'altro. Nient'altro in effetti.
Orione,

3
In realtà /dev/nullè uno dei pochi percorsi standardizzati , insieme a /dev/tty, /dev/console, /tmp, /dev/e /.
Gilles 'SO-smetti di essere malvagio' il

2
@MarkPlotnick In realtà cat è un built-in ksh93 (non abilitato a meno che non lo metti /opt/ast/binprima /bin(o ovunque catsia disponibile) in $PATH). E sì, anche se cat file > /dev/nullcon quel builtin fa readil contenuto di file, non lo scrive in / dev / null (anche se si apre e lo si fstats).
Stéphane Chazelas,

14

Non ottimizzerà i comandi in esecuzione (e hai già ricevuto una serie di risposte precise che ti spiegano perché non dovrebbe), ma in alcuni casi può ottimizzare forcelle, pipe / socketpairs, letture. Il tipo di ottimizzazioni che può fare:

  • Con la maggior parte delle shell moderne, l'ultimo comando in uno script verrà generalmente eseguito nel processo della shell a meno che non trapsiano stati impostati alcuni s. Ad esempio in sh -c ls, la maggior parte shdelle implementazioni ( bash, mksh, ksh, zsh, yash, alcune versioni di ash) non saranno fork di un processo per l'esecuzione ls.
  • in ksh93, la sostituzione dei comandi non creerà un pipe o fork un processo fino a quando non viene chiamato un comando esterno ( $(echo foo)ad esempio si espanderà foosenza pipe / socketpair o fork).
  • l' readintegrato di alcune shell ( bash, AT&T ksh) non eseguirà letture a byte singolo se rilevano che lo stdin è ricercabile (nel qual caso eseguiranno letture di grandi dimensioni e ricercheranno alla fine di ciò che devono leggere).

Mi piace questa risposta, ma non è chiaro se questo sia un motivo originale o se le informazioni sono prese da qualche riferimento (che vorrei approfondire)
yoniLavi

3
@yoniYalovitsky, questa è la ragione originale . ksh93è la shell che apre la strada al fronte dell'ottimizzazione in quanto il suo obiettivo è / doveva essere visto alla pari con linguaggi di programmazione come perl. Quindi puoi dare un'occhiata alla kshdocumentazione, al codice (buona fortuna) e alla mailing list per ulteriori informazioni.
Stéphane Chazelas,

1
@HenkLangeveld, sì, puoi verificare ciò con sh -c 'ps -p "$$"'cui ti darà pse non shcon quelle shimplementazioni, o con strace / truss / tusc ...
Stéphane Chazelas

1
La differenza tra ksh -c 'ps; ps'e bash -c 'ps; ps' è interessante. Ksh93 va oltre nella sua ottimizzazione.
Henk Langeveld,

1
@HenkLangeveld, dipende dall'implementazione di kshcui stiamo parlando qui. mkshsi comporta come bash. Quel comportamento è principalmente pensato per ottimizzare cose come system("some command"). Si noti che c'è un effetto collaterale di tale ottimizzazione quando si tratta dello stato di uscita dei processi terminati da un segnale (in alcune shell). ksh93aveva un bug nel fatto che stava facendo l'ottimizzazione anche quando venivano impostate le trappole.
Stéphane Chazelas,

7

Quando si vede cat hugeregularfile.txt > /dev/null, alla shell non è permesso credere che l'azione sia inutile - catnon fa parte della shell e potrebbe fare qualsiasi cosa in teoria e anche in pratica.

Ad esempio, l'utente potrebbe aver rinominato l'eseguibile rmin cate improvvisamente la linea esegue un comportamento osservabile esternamente, ovvero rimuovendo il file.

L'utente potrebbe aver compilato una versione catche va in un ciclo infinito, quindi la shell non può presumere che sia "noto per terminare" come suggerisci.

Qualcuno potrebbe aver installato una versione catche funziona come previsto, ma con un effetto collaterale aggiuntivo di installare un rootkit se mai eseguito con privilegi adeguati - di nuovo, la shell dovrebbe eseguirlo debitamente.


2
In realtà, mkshin effetti ottimizza V=$(cat file)rendendolo un built-in. Quindi la shell può ottimizzarlo, ma non trasformarlo in solo a touch -a.
Steve Schnepp,

1
@SteveSchnepp, cat è un built-in mksh, ma quel builtin ricorre al sistema catse viene passata qualsiasi opzione, motivo per cui con GNU cat, mksh -c 'cat /dev/null --help'non produce lo stesso risultato di bash -c 'cat /dev/null --help', ma mksh -c 'cat --help /dev/null'ti dà lo stesso di bash -c 'cat --help /dev/null'(poiché il mkshbuilt-in cat analizza le opzioni POSIX mentre GNU li analizza in modo GNU).
Stéphane Chazelas,

In bash e ksh93, è V=$(cat file)possibile ottimizzare con V=$(< file). Questo accelera le cose anche senza un built-in cat.
Henk Langeveld,
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.