![Bash: 억제 후 stderr 다시 열기](https://linux55.com/image/144266/Bash%3A%20%EC%96%B5%EC%A0%9C%20%ED%9B%84%20stderr%20%EB%8B%A4%EC%8B%9C%20%EC%97%B4%EA%B8%B0.png)
git을 자동으로 설치/제거하도록 이 스크립트를 만들었습니다. git이 설치되었는지 테스트하는 함수에서는 명령어를 사용하여 git --version
반환 코드를 테스트합니다.
나는 멋진 사용자 정의 출력을 만들려고 노력하고 있기 때문에 정상적으로 발생하는 stderr 출력을 좋아하지 않습니다. 이 기능에 대해서만 stderr을 억제하는 방법을 알아냈지만 다시 활성화할 수는 없습니다.
이 함수를 호출하면 read
프롬프트가 사라집니다.
function CheckGit() {
exec 3>&2 # link file desc 3 w/ stderr
exec 2> /dev/null
SILENT_MODE=$1
if [[ ! $(git --version) ]]; then
if [ SILENT_MODE ]; then
printf "${LT_RED} GIT IS NOT INSTALLED.\n"
fi
continue;
else
if [ SILENT_MODE ]; then
printf "${LT_BLUE} GIT IS CURRENTLY INSTALLED.\n"
fi
continue;
fi
GIT_INSTALLED=$?
#turn back on the stderr notifications
exec 2>&3 3>&- # Restore stdout and close file descriptor #3
}
while true; do
printf "${LT_BLUE} Menu\n"
printf " ***********************************************\n"
printf "${LT_GREEN} a) Check git.\n"
printf "${LT_GREEN} b) (More to be added)\n"
printf "${LT_GREEN} c) ...\n"
printf "${LT_GREEN} d) ...\n"
printf "${LT_GREEN} h) ...\n"
printf "${LT_RED} x) Exit.\n"
printf "\n${NC}"
read -p "Please make a selection: " eotuyx
case $eotuyx in
[Aa]* ) CheckGit true; continue;;
[Bb]* ) ...; continue;;
[Cc]* ) ...; continue;;
[Dd]* ) ...; continue;;
[Hh]* ) ...; continue;;
[XxQq]* ) break;;
* ) -e "\n${NC}" + "Please answer with a, b, c, d, x(or q).";;
esac
done
답변1
주어진 조언을 반복한다댓글에서:
continue
함수에서 명령문을 제거합니다CheckGit
.- 그것들은 필요하지 않습니다.
- 그리고 - 당신은 그것을 깨닫지 못할 수도 있습니다 - 이는 (함수에서) 메인 루프로 즉시 반환될 뿐만 아니라
while true
메인 루프의 맨 위에 있는 명령문으로 즉시 반환됩니다. 그러므로 다음과 같이토마스는 지적했다, 귀하의exec 2>&3 3>&-
명령문이 실행되지 않았습니다.
일반 사항:
if [ SILENT_MODE ]
항상 옳으니까Mosvi가 지적했습니다., 문자열이SILENT_MODE
비어 있지 않은지 여부만 테스트하기 때문입니다. 당신은 을 원하는 것 같습니다if [ "$SILENT_MODE" ]
.- 하지만 농담일 수도 있습니다. is가 true
if [ "$SILENT_MODE" ]
인 경우에도 수행하는 작업은 문자열이 null이 아닌지 테스트하는 것뿐이므로 호출하면 여전히 정보가 표시됩니다.$SILENT_MODE
false
CheckGit false
- 그리고 자신을 속이지 않더라도 다음 주에 이 스크립트를 유지 관리해야 하는 사람들을 속일 수도 있습니다. 그래, 그 사람이 바로 당신일 수도 있다. 귀하의 명백한 논리는 "자동 모드인 경우 추가 정보를 보고하십시오"입니다. 이는 논리적으로 반대입니다.
if [ "$SILENT_MODE" = false ]
변수를 말하거나 호출하는 것이 더 합리적입니다VERBOSE_MODE
. $?
수명이 매우 짧습니다. 항상 이런 결과가 나오네요최근 주문들. 그래서 만약 당신이 그렇게한다면만약에 Git이 설치되어 있는지 확인;그 다음에 printf "GIT가 설치되지 않았습니다.\n" 기타 printf "GIT가 현재 설치되어 있습니다.\n" 필리핀 제도 GIT_INSTALLED = $?
그런 다음GIT_INSTALLED
종료 상태를 얻으십시오printf
.GIT_INSTALLED
미리 설정해 주셔야 합니다 .- 귀하의 테스트는
if [[ ! $(git --version) ]]; then
"반환 코드"(귀하의 질문에서 언급한 대로)를 테스트하는 것이 아니라git --version
표준 출력에 기록되는 항목이 있는지 테스트하는 것입니다. 이것이 당신이 원하는 것일 수도 있습니다. 이것이git
설치되었는지 테스트하는 가장 좋은 방법 일 것입니다 . 그러나 명령의 종료 상태를 확인하는 것이 더 나을 수도 있습니다(보통 더 나을 수도 있습니다). - 스타일 참고:
if
"진짜" 부분이 먼저 오면 진술을 이해하기가 더 쉽습니다then
.else
귀하의 스크립트는 다음과 같이 말합니다Git이 설치되지 않은 경우 그 다음에 설치되어 있지 않다고 하네요 그렇지 않은 경우(즉,아니요설치되지 않음) 이미 설치됐다고 하네요 필리핀 제도
이중 부정은 혼란스럽습니다. - 그리고 그렇습니다.
exec 2> /dev/null
42개의 연속된 명령문에 대한 표준 오류를 억제하려는 경우 편리합니다. 단일 명령에만 영향을 주어야 하는 경우 다음과 같이 해당 명령에2> /dev/null
(또는 )를 입력하면 됩니다.> /dev/null 2>&1
좀 더 나은 제안.
답변2
명령이 좋아 보이지만 논리가 모든 경우를 포괄하지는 않습니다. continue
실행 시 설명자는 반전되지 않습니다 .
또한 작동 방식과 실제로 작동하는 방식을 분석하십시오.
GIT_INSTALLED=$?
$?
마지막으로 실행된 명령의 종료 코드입니다. 디버깅을 사용하여 이를 더 자세히 살펴보세요( set -x
).
또한 초보자는 정적 테스트 스크립트를 통해 큰 이점을 얻을 수 있습니다.shellcheck.net.