저는 ZSH를 기본 셸로 사용하고 그 위에 OhMyZsh를 사용합니다. 때로는 일부 파일을 삭제하고 일부 권한/소유권을 재설정해야 하므로 해당 별칭을 사용합니다. PHP/Symfony 프로젝트가 있다고 가정해 보겠습니다 /home/parallels/Development/prj1
. 아래 스크립트를 사용하면 실행할 수 있지만 fixperms prj1
...
- 스크립트를 한 번 실행하고 내용을 삭제하면
$CURRENT_PROJECT/$PROJECT_CACHE
다음 오류가 발생합니다.
fixperms:4: no matches found: /home/parallels/Development/prj1/framework/var/cache/*
*
끝 부분을 삭제하면 원하지 않는 폴더도$CURRENT_PROJECT/$PROJECT_CACHE/*
삭제됩니다.cache
파일은
dev.log
절대 삭제되지 않습니다
내가 여기서 무엇을 놓치고 있는 걸까요?
PROJECT=framework
PROJECT_VAR=$PROJECT/var
PROJECT_CACHE=$PROJECT_VAR/cache
PROJECT_LOG=var/log/dev.log
fixperms () {
if [ -n "$1" ]; then
CURRENT_PROJECT=$HOME/Development/"$1"
cd $CURRENT_PROJECT && sudo rm -rf $CURRENT_PROJECT/$PROJECT_CACHE/* && sudo rm -rf $CURRENT_PROJECT/$PROJECT_LOG && sudo chown -R "$(whoami)":root $CURRENT_PROJECT && sudo chmod -R 777 $CURRENT_PROJECT/$PROJECT_VAR
else
echo "Missing project param."
fi
}
참고: 저는 bash/shell 스크립팅 전문가가 아니므로 어떤 개선이라도 환영하며 미리 감사드립니다.
답변1
모든 작업을 연결하면 &&
그 중 하나가 실패하면 작업이 중단되고 해당 줄 이후의 작업은 실행되지 않습니다. 이것이 의도적인 것인지 아닌지는 확실하지 않습니다.
예를 들면 다음과 같습니다.
echo A && false && echo B
echo A && true && echo B
따라서 dev.log
항목 캐시가 실패해도 삭제되지 않는 이유는 무엇입니까? 이 줄 rm
이후의 내용은 실행되지 않습니다.rm -rf $CURRENT_PROJECT/$PROJECT_CACHE/*
zsh
기본적으로 꺼져 있으므로 nullglob
실패 *
합니다.
그래도;
디렉토리가 비어 있는지 먼저 확인한 다음 나중에 확인할 수 있습니다 rm
. 가장 쉬운 방법은 간단히 삭제하고 다시 만드는 것입니다.
setopt nullglob
아니면 나중에 선택하셔도 됩니다 unsetopt nullglob
.
기타 참고사항:
대문자 변수를 사용하는 이유가 있을 수 있지만 가능하면 사용하지 않는 것이 가장 좋습니다. 환경 변수, 내장 함수 등으로 인해 충돌이 발생할 수 있습니다.
더 많이 인용해야합니다.
나는 $project_log
그것이 파일이라고 가정하고 있다면 -r
그것은 쓸모가 없습니다.
echo
/ printf
오류가 발생했습니다 stderr
.
project=framework
project_var=$project/var
project_cache=$project_var/cache
project_log=var/log/dev.log
fixperms () {
if [ -n "$1" ]; then
current_project="$HOME/Development/$1"
# Change to project directory. Exit if it fails.
# The shell should give descriptive error.
pushd "$current_project" || exit 1
[ -e "./$project_cache/" ] && sudo rm -r "./$project_cache/"
sudo mkdir "./$project_cache"
[ -e "./$project_log" ] && sudo rm "./$project_log"
sudo chown -R "$(whoami):root" .
sudo chmod -R 777 "./$project_var"
# Restore directory we started from
popd
else
printf 'fixperms(): Missing argument: project\n' >&2
fi
}
return 1
대신 원하는 것은 exit 1
전적으로 기능을 사용하는 방법에 따라 다릅니다.
어쨌든, 존재 여부를 확인하면 -f
삭제합니다.rm
답변2
sudo rm -rf $CURRENT_PROJECT/$PROJECT_CACHE/*
명령이 실행되는 방법은 다음과 같습니다(중요한 부분만 언급함).
- 쉘은 마지막 인수의 변수를 확장합니다. 밝혀지다
/home/parallels/Development/prj1/framework/var/cache/*
. - 마지막 매개변수에는 와일드카드 패턴이 포함되어 있으므로 패턴이 파일과 일치하는지 확인합니다. 귀하의 계정에는 나열된 파일에 대한 권한이 없으므로
/home/parallels/Development/prj1/framework/var/cache
패턴은 어떤 파일과도 일치하지 않습니다(셸은 "일치하는 파일이 없는지 확인할 수 있습니다"와 "일치하는 파일이 있는지 확인할 수 없습니다"를 구별할 수 없습니다). 어떤 파일과도 일치하지 않는 와일드카드 패턴은 유지됩니다. - 쉘은 프로그램을 실행하기 위해 매개 변수
sudo
를 사용합니다 .rm
-rf
/home/parallels/Development/prj1/framework/var/cache/*
sudo
rm
매개변수를 사용-rf
하고 실행합니다/home/parallels/Development/prj1/framework/var/cache/*
.rm
지정된 파일을 삭제합니다. 즉,*
라는 디렉터리에 파일이 있으면/home/parallels/Development/prj1/framework/var/cache
해당 파일이 삭제됩니다(*
디렉토리인 경우 해당 내용이 반복적으로 삭제됩니다).
와일드카드 확장(또는 삭제할 파일을 열거하는 데 사용되는 모든 방법)을 수행하려면 디렉터리에 대한 읽기 권한이 있는 셸을 준비해야 합니다. 이는 sudo를 호출하는 셸이 아니라 sudo에서 실행되는 셸에서 와일드카드 확장이 발생해야 함을 의미합니다. 예를 들어:
sudo sh -c 'rm -rf "$0"/*' "$CURRENT_PROJECT/$PROJECT_CACHE"
크기 조정 시 주의 사항을 참고하시기 바랍니다. 변수가 내부 셸에 정의되어 있지 않기 때문에 작동하지 않습니다(실행되지만 sudo sh -c 'rm -rf $CURRENT_PROJECT/$PROJECT_CACHE/*'
rm -rf //*
시도해야 할 것은 아닙니다). 이는 관련된 변수 값에 공백과 같은 문자가 포함되지 않은 경우에만 작동합니다. 이러한 값은 파일 이름이 아닌 쉘 코드 조각으로 해석되기 때문입니다.sudo sh -c "rm -rf $CURRENT_PROJECT/$PROJECT_CACHE/*"
알아채다위 명령을 실행하지 않는 것이 좋습니다., 취약하기 때문입니다. 경로가 예상한 것과 정확히 일치하지 않으면 결국 시스템의 모든 항목이 삭제될 수 있으며 명령이 루트로 실행되므로 이는 매우 나쁠 수 있습니다. 대신 필요한 권한이 있는 경우에만 명령을 실행해야 합니다.
sudo -u parallelsowner sh -c 'rm -rf "$0"/*' "$CURRENT_PROJECT/$PROJECT_CACHE"
또는
sudo -g parallelsgroup sh -c 'rm -rf "$0"/*' "$CURRENT_PROJECT/$PROJECT_CACHE"
parallelsowner
문제의 디렉터리와 해당 하위 디렉터리를 소유한 사용자 또는 parallelsgroup
디렉터리와 모든 하위 디렉터리에 대한 쓰기 권한이 있는 그룹은 어디에 있습니까?