내 i3 구성에는 다음 줄이 있습니다.
bindsym $Super+Shift+F10 exec --no-startup-id ps aux | grep -q '[p]icom' && killall picom || picom
키 바인딩을 누르면 쉘 명령이 실행됩니다(--no-startup-id 이후의 모든 것은 쉘 명령입니다). 쉘 명령을 사용하면 데스크탑에서 Picom을 사용하여 구성을 전환할 수 있었습니다. 명령을 실행하고 ps를 사용하여 모든 프로세스 목록을 가져온 다음 grep을 사용하여 "picom"을 검색합니다. grep이 무언가를 찾으면 true를 반환하고 Killall은 실행 중인 모든 piccom을 종료합니다. grep이 아무것도 찾지 못하면 piccom을 시작합니다.
그런데 문제는 명령에 "picom"이 두 번이라도 있으므로 grep이 항상 이를 확인하고 true를 반환해야 하므로 명령이 항상 실행되어야 한다는 killall picom
것입니다.
이것이 사실인지 확인하기 위해 tee를 추가하여 ps의 출력을 log1이라는 파일에 기록하도록 명령을 수정했습니다.
bindsym $Super+Shift+F10 exec --no-startup-id ps aux | tee log1 | grep -q '[p]icom' && killall picom || picom
cat log1 | grep picom
위의 i3 키 바인딩을 사용한 후 picom 없이 실행할 때의 출력은 다음과 같습니다.
ordici 19951 0.0 0.0 3192 2040 ? Ss 17:24 0:00 /bin/sh -c ps aux | tee log1 | grep -q '[p]icom' && killall picom || picom
그래서 제가 옳았습니다. ps의 출력에는 picom이 실행되고 있지 않더라도 picom이 포함되어 있었습니다. 그렇다면 이 명령이 완벽하게 작동하는 이유는 무엇일까요?
더 이상한 점은 i3 키 바인딩 대신 터미널에서 명령을 실행하고 피콤이 실행되지 않는 경우 로그에 ps 명령이 없다는 것입니다. 그러나 예상대로 명령은 여전히 작동합니다.
답변1
이 문제에 대해 글을 쓰면서 나는 그것이 왜 작동하는지 깨달았습니다. 나는 이 글을 헛되이 쓰지 않기 위해 어쨌든 게시할 것이라고 생각했습니다.
grep picom
내 시나리오에서는 예상대로 복용량이 항상 true를 반환합니다. 따라서 항상 실행됩니다 killall picom
. 마치 명령이 다음과 같습니다(이것이 제가 지금부터 사용할 것입니다).
killall picom || picom
작동하는 이유는 killall
종료 값도 있기 때문입니다! 종료할 "picom"이라는 프로세스가 발견되지 않으면 killall
0이 아닌 종료 값을 반환합니다. 그러면 실패하기 전에 명령에 따라 picom이 실행됩니다!
따라서 둘 다 grep
또는 killall
실패하면 picom
원래 명령에서 실행이 실행될 수 있습니다. 이것이 if 문과 "&& ||" 같은 논리 연산자의 차이점입니다. 논리 연산자는 &&
AND 연산자( ) 체인의 여러 명령이 실패하여 OR 연산자( ||
)를 트리거합니다.
테스트를 위해 원래 명령을 if 문으로 변경했습니다.
if ps aux | grep -q '[p]icom'; then
killall picom
else
picom
fi
그리고 실행 여부를 결정하는 유일한 요인은 picom
의 반환 값이고 이 경우 항상 true를 반환하기 때문에 명령이 예상대로 전환되지 않습니다.killall
picom
grep
grep
답변2
실행되지 않으면 자동으로 실패하는 데 왜 귀찮게 ps
하고 grep
-ing합니까 ? 다음과 같이 할 수 있을 것 같습니다.picom
killall
killall picom || picom
명령 결과(종료 상태)에 대한 여러 조건부 테스트는 다음과 같습니다.
grep -q '[p]icom' && { killall picom; true; } || picom
if-else를 사용하지 않고 이 작업을 수행하는 방법입니다. 왜냐하면 지금 발견한 것처럼 a && b || c
이것은 그렇지 않기 때문입니다.삼항 연산자, 즉 이는 다음을 의미하지 않습니다.
if a; then
b
else
c
fi
이것이 의미하는 바는 ( es
=종료 상태)입니다:
a; es=$?
if (( es == 0 )); then
b; es=$?
fi
if (( es != 0 )); then
c; es=$?
fi
(exit $es)
바라보다bash if 문 및 조건부 실행 논리관련 답변은 위의 내용을 더 명확하게 만드는 데 도움이 될 수 있습니다.