Perché POSIX richiede che determinati incorporati della shell abbiano un'implementazione esterna?


19

Da questa domanda sul fatto che printf sia un built-in per yash , arriva questa risposta che cita lo standard POSIX .

La risposta sottolinea che la sequenza di ricerca POSIX è quella di trovare un'implementazione esterna del comando desiderato, quindi, se la shell lo ha implementato come built-in, eseguire il built-in. (Per i built-in che non sono built-in speciali .)

Perché POSIX ha questo requisito per l'esistenza di un'implementazione esterna prima di consentire l'esecuzione di un'implementazione interna?

Sembra ... arbitrario, quindi sono curioso.


Credo che sia un modo per abilitare / disabilitare i builtin se desiderato / richiesto.
Isaac,

2
Disabilitare il built-in rimuovendo l'implementazione esterna? Ora non ci sono comandi di nome printfdisponibili.
Studog

@studog, quindi crea un file vuoto con lo stesso nome del built-in, attiva il bit di esecuzione e inseriscilo in una directory nel tuo PERCORSO. : P
Wildcard il

@Wildcard Una shell rigorosamente conforme vedrebbe quindi il nome durante la ricerca PATHe quindi chiamerà l'utilità integrata, non lo script esterno. E se desideri chiamare lo script esterno nel tuo percorso? Hmm ... Questo sembra richiedere una tabella che descriva le diverse possibilità. Ce n'è uno qui , ma per me non ha senso.
Kusalananda

@Kusalananda, re la tua prima frase, quello era il mio punto. Ecco perché ho detto di creare un file vuoto .
Wildcard il

Risposte:


15

Questa è una regola "come se".

In poche parole: il comportamento della shell quando gli utenti lo vedono non dovrebbe cambiare se un'implementazione decide di rendere disponibile anche un comando esterno standard come shell integrata.

Il contrasto che ho mostrato su /unix//a/496291/5132 tra i comportamenti (da un lato) delle conchiglie PD Korn, MirBSD Korn e Heirloom Bourne; (d'altra parte) le conchiglie Z, 93 Korn, Bourne Again e Debian Almquist; e (sulla mano avvincente) il guscio Watanabe lo evidenzia.

Per le shell che non hanno printfcome built-in, la rimozione /usr/binda PATHfa invocare l' printfinterruzione del funzionamento. Il comportamento conforme POSIX, esposto dalla shell Watanabe nella sua modalità conforme, provoca lo stesso risultato. Il comportamento della shell che ha un printfbuilt-in è come se stesse invocando un comando esterno.

Considerando che il comportamento di tutte le shell non conformi non cambia se /usr/binviene rimosso da PATH, e non si comportano come se stessero invocando un comando esterno.

Ciò che lo standard sta cercando di garantirvi è che le shell possono incorporare tutti i tipi di comandi normalmente esterni (o implementarli come proprie funzioni di shell), e otterrete comunque lo stesso comportamento dai built-in con i comandi esterni se si regola PATHper interrompere la ricerca dei comandi. PATHrimane il tuo strumento per selezionare e controllare quali comandi puoi invocare.

(Come spiegato su /unix//a/448799/5132 , anni fa le persone hanno scelto la personalità del loro Unix cambiando ciò che accadeva PATH.)

Si potrebbe affermare che far funzionare sempre il comando indipendentemente dal fatto che sia possibile trovarlo PATH è in effetti il ​​punto di creare comandi normalmente esterni incorporati. (È per questo che il mio set di strumenti nosh ha appena ottenuto un printenvcomando integrato nella versione 1.38, in realtà. Anche se questa non è una shell.)

Ma lo standard ti dà la garanzia che vedrai lo stesso comportamento per i normali comandi esterni che non sono attivi PATHdalla shell come vedrai da altri programmi non shell che invocano la execvpe()funzione, e la shell non sarà magicamente in grado di eseguire (apparentemente) normali comandi esterni che altri programmi non riescono a trovare con lo stesso PATH. Tutto funziona in modo auto-coerente dal punto di vista dell'utente ed PATHè lo strumento per controllare come funziona.

Ulteriori letture


13

È abbastanza assurdo ed è per questo che nessuna shell lo sta implementando nella sua modalità predefinita.

La logica dello standard e il suo esempio illustrativo suggeriscono che si trattava di un tentativo fallito di avere un normale built-in associato a un percorso e di consentire all'utente di sovrascriverlo facendo apparire il proprio binario prima di esso PATH(ad esempio un printfbuilt-in associato a /usr/bin/printfpotrebbe essere sovrascritto dal /foo/bin/printfcomando esterno impostando PATH=/foo/bin:$PATH).

Tuttavia, lo standard non ha finito per richiederlo, ma qualcosa di completamente diverso (e anche inutile e inaspettato).

Puoi leggere di più al riguardo in questa segnalazione di bug . Citando dal testo finale accettato :

Molte implementazioni esistenti eseguono un normale built-in senza eseguire una ricerca PATH. Questo comportamento non corrisponde al testo normativo e non consente agli autori di script di ignorare le normali utilità integrate tramite un PERCORSO appositamente predisposto. Inoltre, la logica spiega che l' intenzione è quella di consentire agli autori di scavalcare i built-in modificando PATH, ma questo non è ciò che dice il testo normativo .

FWIW, non credo ci sia nessuna shell che implementa i requisiti rivisti dal testo accettato, neanche.


Vedi anche la discussione su article.gmane.org/gmane.comp.standards.posix.austin.general/… (e ce ne sono stati molti altri).
Stéphane Chazelas,


No, (ad esempio un built-in printf associato a / usr / bin / printf potrebbe essere ignorato dal comando / foo / bin / printf esterno impostando PATH = / foo / bin: $ PATH). , non è corretto. L'esistenza di / entrambi / qualsiasi /usr/bin/printfo /foo/bin/printfnel PERCORSO attiverà la stampa integrata. L'unica cosa che printffarà un esterno mancante (nel PERCORSO) è disabilitare l'integrato. (Dalla lettera della specifica).
Isaac
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.