Risposte:
Probabilmente per semplificare il kernel. Non credo che il kernel abbia mai cercato il tuo percorso per trovare un eseguibile. Questo è gestito dalla biblioteca C. #!
l'elaborazione viene eseguita nel kernel, che non utilizza la libreria C standard.
Inoltre, non penso che il kernel abbia un'idea di quale sia il tuo percorso. $PATH
è una variabile di ambiente e solo i processi hanno un ambiente. Il kernel no. Suppongo che potrebbe accedere all'ambiente del processo che ha eseguito il exec, ma non credo che nulla attualmente nel kernel acceda mai a variabili di ambiente del genere.
Puoi ottenere la PATH
semantica di ricerca usando env
, quindi:
#!/usr/bin/env ruby
ha la semantica da cui vorresti
#!ruby
La ragione per cui, a seconda di ciò, PATH
non è considerata una buona pratica, è che lo script non può fare ipotesi sul contenuto della variabile d'ambiente PATH, rompendo il "modello di dipendenza sequenziale" dei binari in cui
/bin
contiene gli eseguibili necessari all'avvio;/usr/bin
contiene gli altri eseguibili utilizzati dall'installazione del sistema operativo;/usr/local/bin
contiene eseguibili installati dall'amministratore di sistema che non fanno parte del sistema operativo di base.~/bin
contiene i file eseguibili dell'utente.Ogni livello non dovrebbe assumere l'esistenza di binari più avanti nella sequenza, che sono più "applicazioni" ma possono fare affidamento su binari precedenti, che sono più "fondamentali". E la variabile PATH tende ad andare dall'applicazione al fondamentale, che è la direzione opposta alla dipendenza naturale sopra.
Per illustrare il problema, chiediti cosa succede se una sceneggiatura ~/bin
invoca una sceneggiatura /usr/local/bin
che invoca Ruby? Lo script dovrebbe dipendere dalla versione installata del SO /usr/bin/ruby
o dalla copia personale in cui si trova l'utente ~/bin/ruby
? PATH
la ricerca fornisce la semantica imprevedibile associata a quest'ultima (forse ~/bin/ruby
è un collegamento simbolico interrotto), mentre si infila nel percorso per #!
dare la prima.
In realtà non esistono altri "sistemi operativi ... informazioni indipendenti dalla piattaforma relativi al percorso per un comando registrato", quindi la cosa più semplice è insistere sul percorso fornito nel file #!
.
Credo che sia così che tu possa specificare un interprete alternativo se ne hai bisogno o vuoi. Per esempio:
#!/home/user/myrubyinterpreter
Più spesso visto con script di shell:
#!/bin/bash
#!/bin/sh
#!/bin/dash
#!/bin/csh
Dal libro di scripting Shell classico :
Gli script Shell in genere iniziano con
#! /bin/sh
. Utilizzare il percorso di una shell conforme a POSIX se/bin/sh
non si è conformi a POSIX. Ci sono anche alcuni "gotchas" di basso livello a cui prestare attenzione:
- Devi conoscere il percorso completo per l'interprete da eseguire. Ciò può impedire la portabilità tra venditori, poiché fornitori diversi collocano le cose in luoghi diversi (ad es.
/bin/awk
Contro/usr/bin/awk
).
Ci sono altre ragioni, ma dal punto di vista della sicurezza non vorrei che uno script facesse ipotesi sul percorso corretto. Che cosa succede se è sbagliato ed esegue la shell o l'interprete sbagliati? Uno che è stato inserito da un utente malintenzionato? O cosa succede se si basa su una particolare shell e si schianta se viene utilizzata la shell sbagliata?
Gli utenti possono scherzare con il loro percorso e rompere le cose - non fidarti dell'utente :-) Ho condotto numerosi attacchi che si basano sull'utente che fa la cosa sbagliata con il suo percorso - di solito portando le cose nell'ordine sbagliato - così posso sovvertire una normale chiamata di script.
Sì, so che se hai scritto la sceneggiatura da solo puoi giustamente affermare di aver risolto il tuo percorso, ma un interprete non può prendere quelle decisioni.
$PATH
. . Senza privilegi elevati, cosa succede se LD_PRELOAD
viene utilizzato? PS Downvoted perché dare un falso avvertimento sulla sicurezza è dannoso per la sicurezza.
PATH
trova un vettore di attacco e non ci sono così tanti altri vettori di attacco che l'intero approccio dovrebbe essere ripensato?
ruby
, ma ciò non ti impedisce di specificare/home/user/myrubyinterpreter
se vuoi