실행 전에 모든 bash 명령을 프로그래밍 방식으로 수정

실행 전에 모든 bash 명령을 프로그래밍 방식으로 수정

이런 종류의 기능이 필요한 프로그램을 만들려고 합니다. 프로세스는 다음과 같습니다.

  • 사용자가 bash 명령을 입력합니다.
  • 사용자가 Enter 키를 누릅니다.
  • 내 스크립트는 명령, 현재 디렉터리를 변수로 가져옵니다. 프로그램은 선택적으로 명령을 수정할 수 있습니다.
  • 수정된 명령은 정상적으로 실행됩니다.

이를 수행할 수 있는 방법이 있습니까?

참고: 이 프로그램은 개인적인 용도로 필요하므로 이 프로그램을 배포하지 않겠습니다.

답변1

나는 이것에 대해 약간의 연구를 했습니다. bash TRAP와 옵션을 사용하여 shopt이를 달성 할 수 있습니다 .

.bash_profile에 추가하세요.

shopt -s extdebug

preexec_invoke_exec () {
    [ -n "$COMP_LINE" ] && return  # do nothing if completing
    [ "$BASH_COMMAND" = "$PROMPT_COMMAND" ] && return # don't cause a preexec for $PROMPT_COMMAND
    local this_command=`HISTTIMEFORMAT= history 1 | sed -e "s/^[ ]*[0-9]*[ ]*//"`;

    # So that you don't get locked accidentally
    if [ "shopt -u extdebug" == "$this_command" ]; then
        return 0
    fi

    # Modify $this_command and then execute it
    return 1 # This prevent executing of original command
}
trap 'preexec_invoke_exec' DEBUG

작동 방식은 다음과 같습니다.

trap 'function_name' DEBUGfunction_namebash 명령이 실행되기 전에 실행 됩니다 . 그러나 기본값 return은 원래 명령에 영향을 주지 않습니다.

shopt -s extdebug일부 디버깅 기능을 활성화합니다. 그 중 하나는 원래 명령을 실행하기 전에 반환 값을 확인합니다.

참고: shopt -u extdebug원래 명령이 항상 실행되도록 이 기능을 비활성화합니다.

문서 extdebug(두 번째 기능 참조):

If set, behavior intended for use by debuggers is enabled:

The -F option to the declare builtin (see Bash Builtins) displays the source file name and line number corresponding to each function name supplied as an argument.
If the command run by the DEBUG trap returns a non-zero value, the next command is skipped and not executed.
If the command run by the DEBUG trap returns a value of 2, and the shell is executing in a subroutine (a shell function or a shell script executed by the . or source builtins), a call to return is simulated.
BASH_ARGC and BASH_ARGV are updated as described in their descriptions (see Bash Variables).
Function tracing is enabled: command substitution, shell functions, and subshells invoked with ( command ) inherit the DEBUG and RETURN traps.
Error tracing is enabled: command substitution, shell functions, and subshells invoked with ( command ) inherit the ERR trap.

답변2

내장된 readline 시스템을 사용하여 줄을 얻는 간단한 bash 스크립트를 사용하여 목표를 달성할 수 있습니다. 예를 들어:

#!/bin/bash -i
while read -e -p '$ ' line
do    echo "your cmd: $line"
      eval "$line"
done

스크립트는 readline 편집(-e)을 사용하여 입력 행(파일의 끝이 아닌 경우)을 읽은 다음 이를 에코하고 실행합니다. 스크립트가 대화형인지 확인하려면 -i위 사항을 참고하세요 . #!이를 기반으로 코드를 작성하여 입력 명령을 조작할 수 있습니다. 예를 들어,

#!/bin/bash -i

myfn(){
  echo "in dir $1. doing: $2" >&2
  echo "$2" # manipulate command here and echo the result
}

while read -e -p "$PS1" line
do    newcmd=$(myfn "$PWD" "$line")
      eval "$newcmd"
done

답변3

설치하다bash-preexec - Zsh와 마찬가지로 Bash용 preexec 및 precmd 기능

두 가지 기능사전 실행그리고사전 명령이제 정의할 수 있으며 존재하는 경우 bash-preexec에 의해 자동으로 호출됩니다.

  • preexec명령을 읽고 실행 직전에 즉시 실행합니다. 사용자가 입력한 문자열이 첫 번째 매개변수로 전달됩니다.
  • precmd각 프롬프트 전에 실행하십시오. PROMPT_COMMAND와 동일하지만 더 유연하고 유연합니다.

.

source ~/.bash-preexec.sh
preexec() { echo "just typed $1"; }
precmd() { echo "printing the prompt"; }

출력은 다음과 유사해야 합니다.

elementz@Kashmir:~/git/bash-preexec (master)$ ls
just typed ls
bash-preexec.sh  README.md  test
printing the prompt

두 개의 서로 다른 배열에 함수를 추가하여 호출할 함수를 정의할 수도 있습니다. 이는 하나의 후크에 대해 많은 함수를 호출하려는 경우 유용합니다.

답변4

모든 셸 스크립트에서 현재 실행 중인 명령을 사용할 수 $0있으며 를 호출하여 현재 디렉터리를 쉽게 검색할 수 있습니다 pwd. 원하는 작업을 수행하려면 쉘로 사용할 수 있는 프로그램을 작성하고 해당 프로그램에 사용자의 쉘 ​​값을 설정해야 합니다.

관련 정보