自動化スクリプトを作成しています。その一環として、cronジョブを追加したいと思います。以下は失敗したスクリプトの一部です。
BACKUP_USER=backupbot
SCRIPT_NAME=backup-script.sh
scp -i ./ssh-key ./$SCRIPT_NAME user@server:/tmp
ssh -i ./ssh-key user@server "
sudo mv /tmp/$SCRIPT_NAME /home/$BACKUP_USER/bin/ &&
sudo chown $BACKUP_USER /home/$BACKUP_USER/bin/$SCRIPT_NAME &&
sudo chmod 100 /home/$BACKUP_USER/bin/$SCRIPT_NAME &&
sudo sed -i 's/THE_URL/'${1}'/' /home/$BACKUP_USER/bin/$SCRIPT_NAME &&
sudo echo '*/1 * * * *' $BACKUP_USER /home/$BACKUP_USER/bin/$SCRIPT_NAME > /etc/cron.d/discourse-backup"
問題のコマンドは次のとおりです。
sudo echo '*/1 * * * *' $BACKUP_USER /home/$BACKUP_USER/bin/$SCRIPT_NAME > /etc/cron.d/discourse-backup
私は得る:
bash:行5:/etc/cron.d/discourse-backup:権限が拒否されました。
この瞬間まですべてがきちんと働いていました。最後のコマンドに何の問題がありますか?私の考えでは、引用符に問題があるようです。一重引用符と二重引用符をさまざまに組み合わせてみましたが、最終的に同じ(またはより悪い)結果を得ました。
ベストアンサー1
次のコマンドを実行すると、
sudo echo some text > file
リダイレクトは、実行前に通常のユーザーとしてシェルで実行されますsudo
。
コメントに答えて編集:
シェルはこれを他のコマンドと比較して特定のコマンドと見なすことはsudo
できません。sudo
シェルの動作は次のようになります。
/bin/echo some text > file
シェルは、上記のコマンドラインのいずれかを解析するときにリダイレクトを探します。したがって、まずファイルを開き、次にプログラムがfork
実行するプロセス、dup
ファイル記述子、およびstdout
プログラムを開きますexec
。その後、リダイレクトが既にある状態で実行するか、/bin/echo
。sudo
stdout
ユースケースでリダイレクトのために一般ユーザーとしてファイルを開くと失敗します。
次のことを試してください
echo '*/1 * * * *' $BACKUP_USER /home/$BACKUP_USER/bin/$SCRIPT_NAME | sudo tee /etc/cron.d/discourse-backup >/dev/null
この場合、ファイルはコマンドライン引数であり、実行され、次にsudo
ファイルroot
名引数を渡すことによってtee
高い権限で実行されます。これにより、tee
ファイルを書き込むために開くことができます。
2番目の編集:この回答は、sudo
他の考えられる問題ではなく、リダイレクトに関連する問題を解決することに焦点を当てています。ユーザーが述べたようにカスコメントでは、変数は個別にまたは完全な文字列として引用する必要があります。
echo "*/1 * * * * $BACKUP_USER /home/$BACKUP_USER/bin/$SCRIPT_NAME" | sudo ...
質問のユースケースでは、参照は2つの理由でそれほど重要ではないかもしれません。パラメーターはのみ使用され、echo
出力は有効なcrontab
行でなければなりません。それにもかかわらず、これは変数に複数の「問題のある」文字が存在することを許可しません。しかし、通常、正しい引用を常に推奨します。
このコマンドは長い引用符で囲まれた文字列の一部になるため、引用符をエスケープできます。
ssh -i ./ssh-key user@server "
...
echo \"*/1 * * * * $BACKUP_USER /home/$BACKUP_USER/bin/$SCRIPT_NAME\" | sudo ... "