Linux에서 Shebang을 통해 Perl과 Python이 잘못 해석되었습니다.

Linux에서 Shebang을 통해 Perl과 Python이 잘못 해석되었습니다.

내 모든 Python 및 Perl 스크립트는 단순히 shebang을 통해 반복되지 않습니다. 절대. 하지만 명시적으로 바이너리를 호출하면 예상대로 작동합니다.

Perl 및 Python 설치를 다시 확인했는데 너무 이상합니다. Shebang 방식 실행은 정상적인 호스트의 대상 시스템 chroot에서는 매우 잘 작동하지만 실제 실행 시스템에서는 작동하지 않습니다.

나는 그 문제가 나타나기 직전에 훌륭하게 작동했던 집에서 만든 Linux 시스템을 작업하고 있습니다. 직접 확인하세요:

'xscreensaver-text' Perl 프로그램에 대한 테스트(한 번은 shebang을 통해, 그 다음에는 CLI의 인터프리터를 사용):

$ LC_ALL=C LANG=C /usr/bin/xscreensaver-text
/usr/bin/xscreensaver-text: line 23: require: command not found
/usr/bin/xscreensaver-text: line 25: use: command not found
/usr/bin/xscreensaver-text: line 29: BEGIN: command not found
/usr/bin/xscreensaver-text: line 31: use: command not found
/usr/bin/xscreensaver-text: line 32: syntax error near unexpected token `('
/usr/bin/xscreensaver-text: line 32: `use POSIX qw(strftime);'

$ LC_ALL=C LANG=C perl /usr/bin/xscreensaver-text
poopy
Linux 3.11.1

Sat Oct  5 23:07:33 2013

up 11:35,  2 users
load average: 0.09, 0.08, 0.06

따라서 이것은 Perl 프로그램의 경우이지만 Python 스크립트에서도 마찬가지입니다. 우리는 인코딩과 terminfo, 그리고 다른 커널을 망쳐봤지만 여전히 성공하지 못했습니다. 심지어 전체 시스템을 재구축하기도 했습니다. chroot 환경에서는 훌륭하게 작동하지만 일단 부팅하면 이런 문제가 발생합니다.

다음은 strace 출력입니다.

$ LC_ALL=C LANG=C strace /usr/bin/xscreensaver-text
execve("/usr/bin/xscreensaver-text", ["/usr/bin/xscreensaver-text"], [/* 50 vars */]) = -1 ENOEXEC (Exec format error)
write(2, "strace: exec: Exec format error\n", 32strace: exec: Exec format error
) = 32
exit_group(1)                           = ?
+++ exited with 1 +++

$ LC_ALL=C LANG=C strace perl /usr/bin/xscreensaver-text
execve("/usr/bin/perl", ["perl", "/usr/bin/xscreensaver-text"], [/* 50 vars */]) = 0
brk(0)                                  = 0x601000
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7ff12e312000
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=240674, ...}) = 0
mmap(NULL, 240674, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7ff12e2d7000
close(3)                                = 0
open("/usr/lib64/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0 \37\2\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=1868472, ...}) = 0
mmap(NULL, 3981888, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7ff12dd24000
mprotect(0x7ff12dee6000, 2097152, PROT_NONE) = 0
mmap(0x7ff12e0e6000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1c2000) = 0x7ff12e0e6000
mmap(0x7ff12e0ec000, 16960, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7ff12e0ec000
close(3)                                = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7ff12e2d6000
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7ff12e2d4000
arch_prctl(ARCH_SET_FS, 0x7ff12e2d4740) = 0
mprotect(0x7ff12e0e6000, 16384, PROT_READ) = 0
mprotect(0x7ff12e313000, 4096, PROT_READ) = 0
munmap(0x7ff12e2d7000, 240674)          = 0
brk(0)                                  = 0x601000
brk(0x622000)                           = 0x622000
clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7ff12e2d4a10) = 5680
wait4(5680, poopy
Linux 3.11.1

Sat Oct  5 23:11:49 2013

up 11:39,  2 users
load average: 0.08, 0.12, 0.08

[{WIFEXITED(s) && WEXITSTATUS(s) == 0}], 0, NULL) = 5680
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=5680, si_status=0, si_utime=2, si_stime=0} ---
exit_group(0)                           = ?
+++ exited with 0 +++

스크립트 내용(시작 부분만):

$ cat /usr/bin/xscreensaver-text
#!/usr/bin/perl -w
# Copyright � 2005-2013 Jamie Zawinski 
#
#
# Created: 19-Mar-2005.

require 5;
#use diagnostics;   # Fails on some MacOS 10.5 systems
use strict;

# Some Linux systems don't install LWP by default!
# Only error out if we're actually loading a URL instead of local data.
BEGIN { eval 'use LWP::UserAgent;' }
--*snip*--

답변1

귀하의 커널은 CONFIG_BINFMT_SCRIPT=y. 이 설정은 shebang 지원을 제어합니다.

에서 make menuconfig:

Symbol: BINFMT_SCRIPT [=y]                                             
   Type  : tristate                                                    
   Prompt: Kernel support for scripts starting with #!                 
     Location:                                                         
   (1) -> Executable file formats / Emulations                         
     Defined at fs/Kconfig.binfmt:68                                   

커널을 재구성하고 다시 컴파일하십시오. (기술적으로 모듈로 구축할 수도 있지만 지원과 같은 기본적인 기능을 위해 그렇게 하는 것은 의미가 없습니다 #!.)

관련 정보