줄 것인가 말 것인가

줄 것인가 말 것인가

shebang에서 프로그램을 사용하고 싶어서 <myscript>라는 스크립트를 만듭니다.

#!<mypgm>

또한 명령 프롬프트에서 <mypgm>을 직접 실행할 수 있기를 바랍니다.

<mypgm> args...

지금까지는 문제가 없습니다.

매개변수를 사용하여 명령 프롬프트에서 <myscript>를 실행할 수 있기를 원합니다.

<myscript> blabla

그러면 shebang은 다음 매개변수를 사용하여 <mypgm>을 호출합니다.

<mypgm> <myscript> blabla

이제 shebang을 사용하여 언제 <mypgm> <myscript> blabla를 호출해야 하는지 알아야 합니다.

myscript blabla # uses the shebang
-or-
<mypgm> myscript blabla   # directly in the command prompt.

환경 변수를 확인했습니다(편집:<====거짓 주장(??,??”) ), 프로세스 테이블(또한 상위 프로세스)에 있지만 차이를 만들 수 있는 방법을 찾지 못했습니다.

지금까지 내가 찾은 유일한 것은 다음과 같습니다.

grep nonvoluntary_ctxt_switches /proc/$$/status

해당 줄이 shebang 바로 뒤에 오는 경우 shebang을 통해 호출할 경우 값은 일반적으로 2(때때로 3)이고, 직접 호출할 경우 일반적으로 1(때때로 2)입니다. 불안정하고 프로세스 스케줄링(프로세스가 CPU에서 분리되는 횟수)에 의존하기 때문에 여기에 더 나은 솔루션이 있는 사람이 있는지 궁금합니다.

답변1

myprg그것이 shebang에서 사용되는지 마술처럼 감지하는 대신 -f명령줄 플래그(예를 들어)를 사용하여 파일을 스크립트로 전달하여 이를 명시적으로 만드는 것은 어떨까요?

의견의 예에서 :

위의 계산 이론 예에서. calc PI + 14.14159를 반환해야 합니다... 이제 shebang(즉, 첫 번째 인수로 파일 이름)에 대한 지원을 추가하면 파일에 포함된 계산이 반환됩니다.

calc스크립트 파일을 가져오고 -f다음 명령을 사용하여 스크립트를 만듭니다.

#!/usr/local/bin/calc -f
$1 + 1

파일을 호출하여 addone.calc실행 가능하게 만들었다고 가정해 보겠습니다. 그런 다음 다음을 사용하여 호출할 수 있습니다.

$ ./addone.calc PI
4.141592...

호출은 에 대한 호출로 변환되므로 /usr/local/bin/calc -f ./addone.calc PI어떤 인수가 스크립트 파일이고 어떤 인수가 스크립트의 인수인지 명확합니다.

awk이는 행동 패턴 및 행동과 유사합니다 sed.

비슷하지만 반대인 접근 방식은 calc기본적으로 스크립트 파일 인수를 사용하지만(shebang과의 사용을 단순화함) 명령줄 플래그를 추가하여 인수의 표현식과 함께 사용하는 것입니다. 이것 역시 비슷하게 작동합니다 sh -c '...'.

답변2

실제 문제는 디자인입니다 <mypgm>. 인수를 해석하는 두 가지 방법을 지원하는 대신 이를 호출하는 두 가지 방법을 제공하십시오.

shebang 명령은 스크립트의 내용을 실행하는 스크립트 엔진이거나 다른 것일 수 있지만 bash실행할 perl스크립트의 파일 이름으로 호출될 것으로 예상됩니다. 어떻게 bash이루어 집니까? 추측하지 않습니다. 옵션(또는 옵션에 대한 인수)처럼 보이지 않는 인수가 발견되면 이를 실행할 스크립트로 간주하고 후속 인수가 스크립트에 전달됩니다. 예를 들어:

/bin/bash -x -e somename foo bar

여기서 bash는 파일을 찾아 인수 somename와 . 너도 똑같은 일을 해야 해 왜냐하면 너는foobar가능한<mypgm> <myscript>언젠가는 명령줄에 글을 쓰고 싶습니다 .

기본적으로 스크립트를 사용하지 않으려면 <mypgm>통과 스크립트를 요구할 수 있습니다 <mypgm> -f <myscript>. 당신은 그렇게 sed않았다 방법. 그런 다음 다음과 같이 shebang 줄에서 사용할 수 있습니다.

#!<mypgm> -f

bash예를 들어 및 를 사용하여 스크립트 대소문자를 기본값으로 지정하려면 perl"이번에는 스크립트 없음" 옵션을 만듭니다. --이를 사용하면 스크립트(또는 다른 것)로 실행을 <mypgm> -- one two three시도하지 않을 수 있습니다 . one이 경우 shebang 줄에는 다음만 표시됩니다.

#!<mypgm>

답변3

이제 shebang을 사용하여 언제 blabla를 호출해야 하는지 알아야 합니다.

C에서는 다음을 통해 해당 정보를 얻을 수 있습니다.getauxval(AT_EXECFN), 원본 실행 파일의 이름(즉, 에 전달된 첫 번째 인수 execve(2))을 알려줍니다[1].

그러나 문자열은 명령줄 인수와 환경 문자열 바로 뒤, 메모리 영역 끝 부분에 배치되므로 [stack]거기에서 직접 가져올 수 있습니다.

예를 들어, 다음 Perl 스크립트(이름을 foo.pl)로 직접 실행하고 다음을 사용하여 실행 가능하게 만든 경우 chmod 755 foo.pl:./foo.pl/usr/bin/perlperl ./foo.pl

#! /usr/bin/perl

open my $maps, "/proc/self/maps" or die "open /proc/self/maps: $!";
my $se;
while(<$maps>){ $se = hex($1), last if /^\w+-(\w+).*\[stack\]$/ }
open my $mem, "/proc/self/mem" or die "open /proc/self/mem: $!";
sysseek $mem, $se - 512, 0;
sysread $mem, $d, 512 or die "sysread: $!";
print $d =~ /([^\0]+)\0+$/, "\n";

최신(>=3.5) Linux 커널에서는 환경 끝이 있을 수도 있습니다 /proc/PID/stat(문서에 설명된 대로 필드 51).proc(5)맨페이지).

#! /usr/bin/perl

open my $sh, "/proc/self/stat" or die "open /proc/self/stat: $!";
my @s = <$sh> =~ /\(.*\)|\S+/g;
open my $mem, "/proc/self/mem" or die "open /proc/self/mem: $!";
seek $mem, $s[50], 0;
$/ = "\0";
my $pn = <$mem> or die "readline: $!"; chomp $pn; print "$pn\n";

[1] 2.6.26 이후의 Linux 커널에는 이를 가리키는 보조 벡터 항목이 도입되었습니다(참조:범죄), 그러나 실행 파일 이름은 그보다 오래 전에(1996년 linux-2.0 이후) 스택 끝에서 사용할 수 있었습니다.

답변4

다음 환경 변수가 모든 작업을 수행한다는 것을 깨달았습니다. $_

<myscript>를 사용하여 시작하면 해당 값은 "./<myscript>"입니다.

<mypgm> <myscript>로 시작하면 해당 값은 <mypgm>의 전체 경로입니다.

내 경우에는 다음과 같이 간단합니다.

#!/bin/bash

how_called=$_

if [[ "X$how_called" == X$0 || "X$how_called" ==X$BASH ]]; then
#                              ^in this case, if the login shell is not bash
   shebang=0
else
   shebang=1
fi

bn=$(basename $0)

나중에 (내 목적을 위해):

if (( shebang == 1 )) || [[ ! -z $1 && "X$1" != X-* && "X$1" == X*\.${bn:0:3} && -x $1 ]]; then 
   # ^ shebang: first argument is the script file
   #                        ^ or not shebang: first argument **may** be a script file name
   #                                                    ^ ensure that this is a script by script extension
   #                                                       (otherwise just use the more verbose but standard --script=...)

   shebang_fn="$1"
   shift 1
   set -- --script="$shebang_fn" "$@" # fall back on standard way.
fi

(여기서 테이블을 약간 뒤집고 있다는 것을 알고 있지만 이것이 이식 가능한 솔루션인지 확인해야 합니다).

관련 정보