私は次のディレクトリ構造を持っています/var/sync
。
# tree -d /var/sync/
/var/sync/
├── sync_bi
│ ├── replicator => Replicator.php
│ sync.php
├── sync_pfizer
│ ├── replicator => Replicator.php
│ sync.php
│ replicator.sh
│ sync.sh
ご覧のとおり、sync_*
各ディレクトリには名前の付いたスクリプトがありsync.php
、replicator
各ディレクトリには名前の付いたスクリプトがありますReplicator.php
。毎晩このスクリプトを実行する必要があります。Replicator.php
午前00:00に実行し、sync.php
午前12:30に実行する必要があります。ここで正しいパスは明らかにクローン操作であることがわかります。 2つのスクリプトを作成し、ほぼ同じコードを共有しreplicator.sh
ますsync.sh
が、最大の違いはスクリプト名です。以下のコードをご覧ください。
replicator.sh
#! /bin/bash
cd $1
/usr/bin/php Replicator.php
sync.sh
#! /bin/bash
cd $1
/usr/bin/php sync.php
次に、次のようにそれぞれのcronjobを追加します。
0 0 * * * /var/sync/replicator.sh /var/sync/sync_bi/replicator/
0 30 * * * /var/sync/sync.sh /var/sync/sync_bi/
0 2 * * * /var/sync/replicator.sh /var/sync/sync_pfizer/replicator/
30 2 * * * /var/sync/sync.sh /var/sync/sync_pfizer/
これらすべての説明の基本的なアイデアは、スクリプトを1回のcronjob呼び出しですべてのタスクを実行し、維持するファイルの数を減らすことができるスクリプトに変更して環境を最適化することです。だから私はいくつかの調査を行い、いくつかの有用なトピックを見つけました。
- 私が使用し
find some/dir -type f -execdir somecommand {} \;
たのと同じことを達成する正しい方法ですか?cd
そして、ルートパスの下の各ディレクトリに移動します。私の場合
/var/sync
for D in ./*; do if [ -d "$D" ]; then cd "$D" run_something cd .. fi done
私が言う擬似コードは次のとおりです(十分に明確ではない場合に備えて)。
read tree structure at /var/sync
foreach (directory in root+path)
if (directory_name is replicator)
cd replicator/
/usr/bin/php replicator.php
else if (directory_name is sync_*)
cd sync_*/
/usr/bin/php sync.php
endforeach
私はbashの専門家ではないので、私の意思コードを私が望むことを達成することができる機能的なものに翻訳するのを手伝ってください。どんな提案や助けがありますか?
修正する
私が間違っているかもしれませんが、あなたがやろうとしていることにまったく従わないのです。したがって、イベントの順序は次のようになります。
# Run Replicator at mid day and mid night
# this two can run at same time since they are pushing data to different DBs
/var/sync/sync_bi/replicator/Replicator.php
/var/sync/sync_pfizer/replicator/Replicator.php
# Run sync at mid day and mid night
# this two should run one first and the second after 30 min since they are
# pushing data to the same DBs and second depends on first one
/var/sync/sync_bi/sync.php
/var/sync/sync_pfizer/sync.php
この情報を考えると(まずはわからないので申し訳ありません)、ソリューションはどのように機能しますか?今はすでに持っているので、それともこの問題を解決するために何かを変更する必要がありますか?
ベストアンサー1
これにより、擬似コードがbashに変換されます。
#!/bin/bash
cd /var/sync
for dir in sync*/ ; do
( # Subshell to make "cd" not global.
cd "$dir"
[[ -f sync.php ]] && /usr/bin/php sync.php
if [[ -d replicator ]] ; then
cd replicator
[[ -f replicator.php ]] && /usr/bin/php replicator.php
fi
)
done
しかし、sync.phpとReplicator.phpの両方を実行しましたが、もともと異なる時間に呼び出すことを望んでいました。たぶん良い
#!/bin/bash
run=$1
cd /var/sync
for dir in sync*/ ; do
( # Subshell to make "cd" not global.
cd "$dir"
[[ -f "$run" ]] && /usr/bin/php "${run##*/}"
)
done
次のようにcronから呼び出されます。
0 30 * * * /path/to/script.sh sync.php
0 0 * * * /path/to/script.sh replicator/Replicator.php
${run##*/}
最後のものより前のすべてを削除します/
。つまり、デフォルト名のみが返されます。
修正する
次のようにスクリプトを実行したい場合:
0:00 sync_a/sync.php
0:30 sync_a/replicator/Replicator.php
1:00 sync_b/sync.php
1:30 sync_b/replicator/Replicator.php
2:00 sync_c/sync.php
...
しばらく、ディレクトリ構造を変更するたびにcrontabを再生成できます。
#!/bin/bash
add=$1
php=/usr/bin/php
hour=0
minute=0
update_time () {
(( minute += add ))
if (( minute >= 60 )) ; then
(( hour += minute / 60 ))
(( minute %= 60 ))
fi
if (( hour > 11 )) ; then
echo "Can't fit into a day!"
exit 1
fi
}
cd /var/sync
for dir in sync*/ ; do
if [[ -f "$dir"/sync.php ]] ; then
echo $minute $hour 0 0 0 "$php" /path/to/run.sh "$dir" sync.php
update_time
if [[ -f "$dir"/replicator/Replicator.php ]] ; then
echo $minute $hour 0 0 0 "$php" path/to/run.sh "$dir" Replicator.php
fi
update_time
fi
done
呼ぶgenerate_crontab.sh 30
か似ています。ファイルはアルファベット順にソートされるため、一部のディレクトリは変更後にスキップされる可能性があります。
run.sh
ただしなければならない
dir=$1
script=$2
if [[ -f "$dir$script" ]] ; then
cd "$dir"
/usr/bin/php $script
fi