Bash 내장으로`exec` 실행


9

쉘 함수를 정의했습니다 (호출하자 clock) . 이 time함수 와 유사한 다른 명령에 대한 래퍼로 사용하고 싶습니다 ( 예 :) clock ls -R.

내 셸 함수는 몇 가지 작업을 수행 한 다음로 끝납니다 exec "$@".

이 기능을 쉘 내장에서도 사용할 수 있기를 원합니다. 예를 들어 실행 파일이 아닌 내장 clock time ls -R결과를 출력해야합니다 . 그러나 항상 대신 명령을 실행합니다.time/usr/bin/timeexec

bash 내장 함수를 인수로 허용하는 래퍼로 Bash 함수를 작동 시키려면 어떻게해야합니까?

편집 : 방금 time배쉬 내장이 아니라 파이프 라인과 관련된 특별한 예약어라는 것을 배웠습니다 . 와 함께 작동하지 않더라도 내장 솔루션에 관심이 time있지만 더 일반적인 솔루션이 더 좋습니다.


를 사용하여 셸을 명시 적으로 호출해야합니다 exec bash -c \' "$@" \'. 첫 번째 매개 변수의 명령이 쉘 스크립트로 인식되지 않으면 직접 실행되는 이진으로 해석됩니다. 또는 더 간단히 말하면, 원래 쉘에서를 빼고 exec호출 "@"하십시오.
AFH

답변:


9

bash 함수를 정의했습니다. 따라서 해당 기능을 호출 할 때 이미 bash 쉘에 있습니다. 따라서 해당 기능은 다음과 같이 간단하게 나타납니다.

clock(){
  echo "do something"
  $@
}

이 함수는 bash 내장, 특수 예약어, 명령 및 기타 정의 된 함수를 사용하여 호출 할 수 있습니다.

별명 :

$ clock type ls
do something
ls is aliased to `ls --color=auto'

bash 내장 :

$ clock type type
do something
type is a shell builtin

다른 기능 :

$ clock clock
do something
do something

실행 파일 :

$ clock date
do something
Tue Apr 21 14:11:59 CEST 2015

이 경우, 실행 사이에 어떤 차이가 $@exec $@내가 실제 명령을 실행하고 알고있는 경우는?
anol

3
을 사용 exec하면 명령이 쉘을 대체합니다. 따라서 실행 파일이 system call을 통해 실행되기 때문에 더 이상 내장, 별명, 특수 예약어, 정의 된 단어가 없습니다 execve(). 그 syscall은 실행 파일을 기대합니다.
혼돈

그러나 외부 관찰자의 관점에서 볼 때, 예를 들어 exec $0단일 프로세스가 있고 $@여전히 두 개가 있지만이 를 구별하는 것이 여전히 가능합니다 .
anol

4
예, $@실행중인 쉘이 상위이고 명령이 하위 프로세스입니다. 그러나 내장, 별명 등을 사용하려면 쉘을 보존해야합니다. 아니면 새로운 것을 시작하십시오.
혼돈

4

쉘 내장 또는 쉘 키워드를 시작하는 유일한 방법은 exec가 "주어진 명령으로 쉘을 대체하기"때문에 새 쉘을 시작하는 것입니다. 마지막 줄을 다음과 같이 바꿔야합니다.

IFS=' '; exec bash -c "$*"

이것은 내 장어와 예약어 모두에서 작동합니다. 원칙은 같습니다.


3

래퍼가 주어진 명령 전에 코드를 삽입해야하는 경우, 매우 초기 단계에서 확장 될 때 별명이 작동합니다.

alias clock="do this; do that;"

별명은 거의 별명으로 된 단어 대신 문자 그대로 삽입되므로 후행 ;이 중요 clock time foo합니다 do this; do that; time foo.

이를 악용 하여 인용을 우회하는 마술 별칭 을 만들 수 있습니다 .


명령 뒤에 코드를 삽입 하려면 "DEBUG"훅을 사용할 수 있습니다.

shopt -s extdebug
trap "<code>" DEBUG

구체적으로 특별히:

shopt -s extdebug
trap 'if [[ $BASH_COMMAND == "clock "* ]]; then
          eval "${BASH_COMMAND#clock }"; echo "Whee!"; false
      fi' DEBUG

후크는 여전히 명령 전에 실행 되지만 반환 false되면 bash가 실행을 취소하도록 지시합니다 (훅이 이미 eval을 통해 실행 되었기 때문에).

다른 예로서, 이것을 사용하여 다음과 같이 별칭 command please을 지정할 수 있습니다 sudo command.

trap 'case $BASH_COMMAND in *\ please) eval sudo ${BASH_COMMAND% *}; false; esac' DEBUG

1

지금까지 내가 취할 수있는 유일한 해결책은 첫 번째 인수가 명령, 내장 또는 키워드인지 여부를 구별하기 위해 사례 분석을 수행하고 마지막 경우에는 실패하는 것입니다.

#!/bin/bash

case $(type -t "$1") in
  file)
    # do stuff
    exec "$@"
    ;;
  builtin)
    # do stuff
    builtin "$@"
    ;;
  keyword)
    >&2 echo "error: cannot handle keywords: $1"
    exit 1
    ;;
  *)
    >&2 echo "error: unknown type: $1"
    exit 1
    ;;
esac

time그러나을 처리하지 않으므로 더 나은 (그리고 더 간결한) 솔루션이있을 수 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.