2016-06-27 28 views
9

perl interpreta lo shebang stesso e simula il comportamento di exec*(2). Penso che emuli il comportamento di Linux della divisione su tutti gli spazi bianchi invece di BSD, la prima cosa solo per gli spazi bianchi, ma non importa.In che modo Perl evita i loop dello shebang?

Proprio come una dimostrazione rapida really_python.pl

#!/usr/bin/env python 

# the following line is correct Python but not correct Perl 
from collections import namedtuple 
print "hi" 

stampe hi quando invocati come perl really_python.pl.

Inoltre, i seguenti programmi faranno la cosa giusta indipendentemente dal fatto che siano invocati come perl program o ./program.

#!/usr/bin/perl 
print "hi\n"; 

e

#!/usr/bin/env perl 
print "hi\n"; 

Non capisco il motivo per cui il programma non è loop infinito. In uno dei casi precedenti, la riga shebang è o si risolve in un percorso assoluto all'interprete perl. Sembra che la prossima cosa che dovrebbe accadere dopo che è perl analizza il file, nota lo shebang e delega al percorso shebang (in questo caso stesso). perl confronta il percorso shebang con il proprio ARGV[0]? perl esamina la stringa shebang e verifica se contiene "perl" come sottostringa?

Ho provato a utilizzare un collegamento simbolico per attivare il comportamento del ciclo infinito che mi aspettavo.

$ ln -s /usr/bin/perl /tmp/p 

#!/tmp/p 
print "hi\n"; 

ma quel programma ha stampato "ciao" indipendentemente da come è stato richiamato.

Su OS X, tuttavia, ero in grado di ingannare perl in un ciclo di shebang infinito con uno script.

Contenuto del /tmp/pscript

#!/bin/sh 
perl "[email protected]" 

Contenuti di script perl

#!/tmp/pscript 
print "hi\n"; 

E questo ciclo infinito (su OS X, non hanno ancora testato su Linux).

perl chiaramente sta andando a un sacco di problemi per gestire correttamente gli shebang in situazioni ragionevoli. Non è confuso da symlink e non è confuso dal normale materiale env. Cosa sta facendo esattamente?

risposta

10

Il codice di riferimento è in toke.c, lexer Perl. Se:

  • linea 1 inizia con #! (eventualmente preceduto da spazi bianchi) E

  • non contiene perl - E

  • non contiene perl (meno seguito da un 6, cioè perl6) E

  • (su piattaforme "DOSISH") non contiene una corrispondenza senza distinzione tra maiuscole e minuscole di perl (ad es. Perl) E

  • non contiene indir E

  • bandiera -c non è stato impostato sulla riga di comando e

  • argv[0] contiene perl

il programma seguendo la faccenda è eseguito con execv. Altrimenti, il lexer continua ad andare avanti; perl non è lo stesso exec.

Di conseguenza, si possono fare alcune cose piuttosto strane con la baracca, senza perl che cercano di exec altro interprete:

#!  perl 
#!foo perl 
#!fooperlbar -p 
#!perl 6 
#!PeRl   # on Windows 

Il vostro esempio collegamento simbolico soddisfa tutte le condizioni sopra elencate, quindi perché isn c'è un ciclo infinito? Si può vedere cosa sta succedendo con strace:

$ ln -s /usr/bin/perl foo 
$ echo '#!foo' > bar 
$ strace perl bar 2>&1 | grep exec 
execve("/bin/perl", ["perl", "bar"], [/* 27 vars */]) = 0 
execve("foo", ["foo", "bar"], [/* 27 vars */]) = 0 

Perl realmente fa exec il link, ma perché non contiene perl nel nome, l'ultima condizione non è più soddisfatta la seconda volta intorno e le estremità del ciclo .

+0

Nota: questo presuppone che l'OP abbia lanciato lo script usando 'perl/tmp/pscript'. La risposta è leggermente diversa quando lo script viene lanciato usando '/ tmp/pscript'. – ikegami

12

La documentazione di questa funzione si trova in perlrun.

Se la linea #! non contiene la parola "perl", né la parola "indir", il programma prende il nome dal #! viene eseguito al posto dell'interprete Perl. Questo è leggermente bizzarro, ma aiuta le persone su macchine che non lo fanno #!, perché possono dire a un programma che il loro SHELL è /usr/bin/perl, e Perl invierà quindi il programma all'interprete corretto per loro .

Quindi, se la baracca contiene perl o indir, l'interprete dalla linea shebang non viene eseguito.

Additionally, l'interprete dalla riga shebang non viene eseguito se argv[0] non contiene perl. Questo è ciò che impedisce il ciclo infinito nel tuo esempio.

  • volta lanciato utilizza perl /tmp/pscript,

    1. il kernel esegue perl /tmp/pscript,
    2. poi perl esegue /tmp/p /tmp/pscript.
    3. A questo punto, argv[0] non contiene perl, quindi la riga shebang non è più rilevante.
  • volta lanciato utilizza /tmp/pscript,

    1. il kernel esegue /tmp/p /tmp/pscript.
    2. A questo punto, argv[0] non contiene perl, quindi la riga shebang non è più rilevante.
+0

E, dal 5.24, la parola "perl6" non è considerata una corrispondenza per "perl", nel senso che se un programma con un perl6 shebang viene eseguito dall'interprete perl5, eseguirà nuovamente perl6, piuttosto che provare a eseguilo da solo 'perlrun' non sembra essere stato aggiornato per riflettere questo. – hobbs

+0

(se si è veramente determinati a ottenere un ciclo, è possibile ottenerne uno collegando symlink per 5.24 come 'perl6', poiché la condizione di interruzione del loop * non * ha questa eccezione.) – hobbs

+0

@hobbs, Il codice per che ho collegato è per 5.24. Ulteriori dettagli possono essere visti lì, e nella risposta ThisSuitIsBlackNot. Stavo limitando la risposta alla portata della domanda, ma ci sono davvero altre regole "nascoste". – ikegami