私は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
とすべてのサブディレクトリに対する書き込み権限を持つグループはどこにありますか?