Linux에서 `#!/usr/bin/env 명령 --argument`를 사용하는 Shebang 라인이 실패합니다.

Linux에서 `#!/usr/bin/env 명령 --argument`를 사용하는 Shebang 라인이 실패합니다.

간단한 스크립트가 있습니다.

#!/usr/bin/env ruby --verbose
# script.rb
puts "hi"

내 OSX 컴퓨터에서는 잘 작동합니다.

osx% ./script.rb
hi

그러나 내 Linux 컴퓨터에서는 오류가 발생합니다.

linux% ./script.rb
/usr/bin/env: ruby --verbose: No such file or directory

Shebang 라인을 수동으로 실행하면 정상적으로 작동합니다.

linux% /usr/bin/env ruby --verbose ./script.rb
hi

ruby --verbose하지만 이를 단일 매개변수로 압축하면 오류를 복제할 수 있습니다.env

linux% /usr/bin/env "ruby --verbose" ./script.rb
/usr/bin/env: ruby --verbose: No such file or directory

env그래서 Shebang Line Reset 문제를 이렇게 설명하는 것 같습니다. 나는 GNU coreutils 8.4를 사용하고 있습니다 env.

linux% /usr/bin/env --version
env (GNU coreutils) 8.4
Copyright (C) 2010 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Written by Richard Mlynarik and David MacKenzie.

정말 이상해 보이네요. 이것이 이 버전의 일반적인 문제입니까 env, 아니면 제가 인식하지 못하는 다른 문제가 있습니까?

답변1

이는 Linux(BSD와 달리)가 shebang 명령(이 경우 env)에 단일 인수만 전달하기 때문인 것 같습니다.

이것은 StackOverflow에서 광범위하게 논의됩니다..

답변2

Coreutils>=8.30:

#!/usr/bin/env -S ruby --verbose

-S또는 env 옵션은 --split-stringGNU coreutils 매뉴얼에 설명되어 있습니다(참조: info '(coreutils) env invocation'또는온라인 매뉴얼). 다음은 발췌 내용입니다:

대부분의 운영 체제(예: GNU/Linux, BSD)는 첫 번째 공백 뒤의 모든 텍스트를 단일 인수로 처리합니다. 따라서 스크립트에서 env를 사용할 때 여러 매개변수를 지정할 수 없습니다.

다음 예에서는:

#!/usr/bin/env perl -T -w print "hello\n";

운영 체제는 이를 perl -T -w매개변수(프로그램 이름)로 처리하고 다음과 같이 스크립트 실행이 실패합니다.

/usr/bin/env: 'perl -T -w': No such file or directory

-S옵션은 env단일 문자열을 여러 인수로 분할하도록 지시합니다. 다음 예제는 예상대로 작동합니다.

$ cat hello.pl
#!/usr/bin/env -S perl -T -w print "hello\n";

$ chmod a+x hello.pl $ ./hello.pl hello

perl -T -w hello.pl명령줄 프롬프트에서 실행하는 것과 동일합니다 .

답변3

@rampion 댓글을 통해 이것을 찾았습니다.

무슨 일이 일어나는지는 커널이 #!를 찾는 파일의 처음 두 문자를 처리한다는 것입니다. 이러한 문자가 발견되면 모든 공백 문자를 건너뛰고 공백이 아닌 문자를 찾고 다른 스크립트가 아닌 실제 실행 파일이어야 하는 인터프리터 경로를 추출합니다. 단, Linux는 재귀 스크립트 처리를 허용하도록 이를 확장합니다. 일단 발견되면 공백이 아닌 첫 번째 문자로 점프하고 거기에서 다음 개행 문자로 점프하여 단일 인수로 명령에 전달합니다. 따옴표나 기타 메타 문자의 "쉘링"은 없습니다. 그것은 모두 매우 단순하고 폭력적입니다. 그래서 당신은 그곳의 옵션에 관심을 가질 수 없습니다. 공백이 포함된 인수를 얻게 되며 "perl -w"는 커널이 여기에서 보고 전달하는 것입니다.

원천:http://lists.gnu.org/archive/html/bug-sh-utils/2002-04/msg00020.html

관련 정보