
/etc/bashrc
시스템 파일에 다음 별칭이 설정되어 있습니다 .
alias root="sudo !!"
이것의 목적은 sudo
코스를 사용하여 마지막으로 사용한 명령을 실행하는 것입니다. 사용하면 history
대화형 쉘에서 bashrc
실행할 때 얻는 실제 명령 이 아니라 쉘이 초기화될 때 파일의 마지막 명령을 대체합니다 . sudo !!
저도 해봤는데 alias root="sudo fc -s"
별 효과 없었어요.
이것이 BASH가 명령 대체를 수행하는 방식과 관련이 있을 수 있다는 것을 알고 있지만, 왜 이런 일이 발생하는지 설명하고 사용 가능한 대체품을 제공할 수 있는 사람이 있습니까?
저는 BASH 버전 3.2.51(1)-릴리스(x86_64-apple-darwin13)를 실행하고 있습니다.
답변1
bash 맨페이지의 2비트는 이 동작의 주요 부분을 설명합니다.
이 HISTORY EXPANSION
섹션의:
히스토리 확장은 쉘이 행을 단어로 나누기 전에 전체 행을 읽은 후 즉시 수행됩니다.
이 ALIASES
섹션의:
각 단순 명령의 첫 번째 단어(따옴표가 없는 경우)를 검사하여 별칭이 있는지 확인합니다.
따라서 기본적으로 역사적 확장은 분사 이전에 발생합니다. 별칭 확장은 나중에 발생합니다.
대체 솔루션
내가 생각할 수 있는 가장 좋은 방법은 다음과 같습니다.
alias root='sudo $(fc -ln -1)'
이는 간단한 명령에는 잘 작동하지만 더 복잡한 명령에는 조정이 필요합니다.
alias root='sudo sh -c "$(fc -ln -1)"'
변경 이유는 다음과 같습니다.
# alias root='sudo $(fc -ln -1)'
# echo "I AM $(whoami)"
I AM patrick
# root
"I AM $(whoami)"
보시다시피 쉘 구문 분석이 수행되지 않았습니다. use 로 변경하면 sh -c "..."
쉘 해석이 가능합니다.
# alias root='sudo sh -c "$(fc -ln -1)"'
# echo "I AM $(whoami)"
I AM patrick
# root
I AM root
다른 방법(저는 이것을 먼저 생각했기 때문에 답변에 그대로 두겠습니다. 그러나 위의 방법만큼 좋지는 않습니다):
alias root='fc -e "sed -i -e \"s/^/sudo /\""'
이 fc -e
명령은 지정된 명령을 실행하고 이전에 실행된 명령이 포함된 파일을 전달합니다. 해당 파일을 실행 sed
하고 명령 앞에 sudo
.
답변2
이런 방식으로 별칭을 사용할 수 없습니다. 별칭은 와 같은 매개변수를 전달할 수 없습니다 !!
. 원하는 효과를 얻으려면 함수를 대신 사용할 수 있습니다.
function root() {
sudo $(history | tail -2 | head -1 | awk '{$1=$2=$3=""; print $0}');
}
그러나 이는 대략적인 생각이며 몇 가지 문제가 있을 수 있습니다. 내 기록 명령 출력은 다음과 같습니다.
$ history
1081 20131205 08:00:12 ls
1082 20131205 08:00:13 history
따라서 이 출력을 구문 분석해야 합니다. 위에서는 기록을 실행하여 마지막 2개의 명령을 가져온 다음 이전에 실행되었던 명령인 마지막 2개의 명령 중 첫 번째 명령을 가져옵니다. 그런 다음 awk
이전에 실행했던 명령줄을 그대로 두고 처음 4개 열을 삭제 했습니다 .
별칭으로?
우리가 출력을 사용하고 있다는 점을 고려하면 history
더 이상 Bash 기능을 사용할 이유가 없습니다. 이전 명령을 매개변수로 전달하려는 경우 이 작업을 수행해야 하지만 history
지금은 이 명령을 통해 가져옵니다.
$ alias root="sudo \$(history | tail -2 | head -1 | awk '{\$1=\$2=\$3=\"\"; print \$0}')"
위의 내용은 별칭으로 변환하는 데 필요한 더 까다로운 이스케이프 처리를 제외하고 이 함수와 유사하게 작동합니다.