
誰も中身を知らないバッチを解読する|止める前に確かめる5つの手順
サーバー移行の打ち合わせで、こう聞かれました。「この daily_job.sh って、新しいサーバーにも持っていくんですよね?」 毎晩2時に動いていることだけは知っている。でも、何をしているのかは、正直わからない。作った人はもういないし、ドキュメントもない。止めたら何か起きる気がして、ずっと触れずにきた——。
引き継いだシステムを守っていると、こういう「正体不明のバッチ」に必ず出会います。答えに詰まるのは、あなたの調べ方が足りないからではありません。誰も書き残さなかったものは、誰が見てもわからないのが当たり前です。
この記事では、ソースを頭から読み込む前に、外側から少しずつバッチの動作を解読していく順番を整理します。一緒に確認していきましょう。
結論:正体不明のバッチは、①いつ・どこから起動されているか → ②動いた痕跡(ログ・更新日時) → ③何を読み、何を書き換えているか(入力と出力) → ④ソースは「外に影響する行」だけ拾う → ⑤わかったことを1枚の「バッチカルテ」に残す の順で解読します。中身を全部理解しなくても、「止めたら何が起きるか」が言えれば十分です。
何が起きているか:バッチは「見えない場所で、静かに」動いている
画面のある機能なら、触ってみれば動きがわかります。でもバッチは、夜中に誰にも見られずに動いて、終わります。だから正体が見えにくいのです。
- 起動元がばらばら:crontab、
/etc/cron.d/の設定、systemd のタイマー、アプリ内のスケジューラなど、仕掛けられている場所が1か所とは限りません。 - 名前が中身を語らない:
daily_job.sh、batch2.php、tmp_fix_old.pl。名前から推測できることはほとんどありません。 - 何かを静かに書き換えている:DBの更新、ファイルの削除、外部へのファイル送信、メール送信。失敗しても気づかれず、止まって初めて「あれが要るものだった」とわかることもあります。
- ソースを開くと迷子になる:長いシェルスクリプトから別のスクリプトやSQLファイルを呼んでいて、読み始めると終わりが見えない。
だからこそ、いきなりソースの1行目から読むのではなく、外から見える事実を先に集めるのがいちばん安全で早い近道です。ここは現場でも迷いやすいところなので、順番を決めておきましょう。
正体不明のバッチを解読する5つの手順

① いつ・どこから起動されているかを押さえる
最初に確かめるのは、何がこのバッチを起動しているかです。ここがわかると、実行時刻・実行ユーザー・引数が一度にわかります。
- crontab:
crontab -l(ユーザーごと。root や実行ユーザーでも確認)、/etc/crontab、/etc/cron.d/配下、/etc/cron.daily/などの定期実行ディレクトリ。 - systemd のタイマー:
systemctl list-timers --allで一覧を見て、気になるものはsystemctl cat <名前>.timerと対応する.serviceの中身を確認。 - それ以外:アプリケーション内のスケジューラ、別サーバーからの ssh 実行、Windows ならタスクスケジューラ。
見つからないときは、バッチのファイル名でサーバー内の設定を検索してみます(例:sudo grep -rn "daily_job" /etc/cron* /var/spool/cron)。サーバー全体の自動実行の洗い出しは、cron・常駐プロセスの棚卸し手順で整理しています。
ここで、実行時刻・実行ユーザー・引数・起動元のファイルをメモしておきます。引数によって動きが変わるバッチは珍しくありません。
② 動いた痕跡を見る:ログと更新日時
次に、実際に動いた跡を探します。設定に書いてあっても、もう失敗し続けている、ということもあるからです。
- バッチ自身のログ:crontab の行末にリダイレクト(
>> /var/log/xxx.log 2>&1など)があれば、その出力先。 - システム側の記録:cron の実行記録(ディストリビューションにより
/var/log/cron、/var/log/syslog、またはjournalctlで確認)。systemd のタイマーならjournalctl -u <名前>.service。 - 更新日時:バッチが書き出しているらしいファイルやディレクトリの更新日時(
ls -l --time-style=full-iso)。実行時刻の直後に更新されていれば、そこが出力先の有力候補です。
ここで「毎晩ちゃんと終わっている」「実は半年前からエラーで止まっている」がわかるだけでも、判断はずいぶん変わります。ログの探し方は大量のログからエラーを絞り込むも参考になります。
③ 何を読み、何を書き換えているか(入力と出力)を洗い出す
いちばん大事なのがこの手順です。バッチの中身を理解するより先に、外とのつながりを洗い出します。
入力(読んでいるもの)
- 読み込むファイル(取り込み用のCSV、設定ファイル)
- 参照するDBのテーブル
- 外部から取ってくるデータ(API、FTP/SFTP など)
出力(書き換えているもの)
- 更新・削除しているDBのテーブル
- 作成・移動・削除しているファイル
- 外部への送信(ファイル転送、API呼び出し、メール送信)
出力のほうが重要です。止めたときに困るのは、たいてい「出力が来なくなった側」だからです。たとえば「毎朝経理が見ている集計テーブルが更新されなくなる」「取引先へのファイル送信が止まる」「古いファイルの削除が止まってディスクが埋まる」など。
DBの更新を見るなら、更新日時のカラムがあるテーブルでバッチの実行時刻前後に更新された行を確かめるのが手軽です(参照だけのSELECTにとどめます)。
④ ソースは「外に影響する行」だけを拾い読みする
ここで初めてソースを開きます。ただし、頭から全部読む必要はありません。まずは外に影響を与える行だけを探します。
- ファイル操作:
rm、mv、cp、>(上書き)、find ... -delete - DB操作:
UPDATE、DELETE、INSERT、TRUNCATE、呼び出しているSQLファイル - 外部とのやり取り:
curl、wget、sftp、scp、mail、sendmail - ほかのスクリプトの呼び出し:呼び出し先も同じ観点で拾う
grep -nE "rm |mv |DELETE|UPDATE|TRUNCATE|curl|sftp|mail" daily_job.sh のように拾うと、どこが「外に影響する場所」かが見えてきます。拾えた行は③の入出力リストと突き合わせて、抜けを埋めます。長いスクリプトの読み進め方は長い関数・巨大ファイルの読み方、なぜそう書かれたかの経緯はgit blameで履歴を追う方法が役に立ちます。
本番でバッチを手で実行して確かめるのは、最後の手段にとどめます。 削除や外部送信を含むバッチは、試しに動かしただけで取り消せない影響が出ることがあります。動きを確かめるなら、検証環境で、送信先や削除対象をダミーに差し替えてから動かすのが安全です。
⑤ わかったことを1枚の「バッチカルテ」に残す
最後に、調べたことを1枚にまとめます。完璧でなくてかまいません。「わからない」も立派な記録です。
| 項目 | 書く内容 |
|---|---|
| 名前・場所 | ファイルのパス、起動元(crontab・タイマーなど) |
| 実行時刻・ユーザー | 毎日2:00、実行ユーザー、引数 |
| 入力 | 読むファイル・テーブル・外部データ |
| 出力 | 書き換えるテーブル・ファイル・外部送信先 |
| 止めたら困る人 | 出力を使っている部署・取引先・後続の処理 |
| 最後に正常終了した日 | ログや更新日時から |
| わからないこと | 未確認の点と、次に調べる場所 |
このカルテが1枚あるだけで、次に「これ止めていい?」と聞かれたとき、「止めると経理の朝の集計が更新されなくなります」と答えられるようになります。運用ドキュメントへのまとめ方は運用ドキュメントに最低限書くべき項目テンプレートで整理しています。
具体例:毎晩2時の daily_job.sh を解読する
冒頭のバッチを、この順番で調べてみます。
- 起動元:root の crontab に
0 2 * /opt/app/bin/daily_job.sh >> /var/log/daily_job.log 2>&1を発見。実行は毎日2時、引数なし。 - 痕跡:
/var/log/daily_job.logを見ると、毎晩数分で終わっている。エラーは見当たらない。 - 入出力:実行時刻の直後に、
/data/export/に日付入りのCSVが作られていた。DBでは集計用テーブルの更新日時が毎晩2時台にそろっていた。 - ソースの拾い読み:
grepで拾うと、集計テーブルのTRUNCATEとINSERT、CSVの作成、そしてsftpで取引先のサーバーへ送っている行が見つかった。さらに、30日より古いCSVをfind ... -deleteで消していた。 - カルテ:「毎晩、売上を集計テーブルに作り直し、CSVにして取引先へ送る。古いCSVの掃除もしている。止めると、取引先にデータが届かなくなり、ディスクも少しずつ埋まる」。
ソースは全部で数百行ありましたが、読んだのは「外に影響する行」の十数行だけ。それでも、移行先に必ず持っていくべきバッチで、取引先への送信先の設定も一緒に移す必要があることがはっきりしました。打ち合わせには、このカルテを持っていけば大丈夫です。
影響:解読しておくと、何が変わるか
- 「止めていいか」に答えられる:移行・廃止・時刻変更の相談に、根拠を持って答えられます。
- 障害のときに迷わない:「朝になったらデータが古い」という問い合わせが来たとき、どのバッチを疑えばいいかがすぐわかります。失敗に早く気づく仕組みはcronバッチの失敗に気づく仕組みが参考になります。
- 怖さが減る:正体がわかったバッチは、もう「触ると何か起きるもの」ではありません。手を入れるかどうかを、落ち着いて選べるようになります。
- 次の人が助かる:カルテが残っていれば、次に引き継ぐ人は同じ調査をしなくて済みます。
明日やること:気になるバッチを1本だけ、①〜③まで調べる
一度に全部のバッチを解読しなくて大丈夫です。今日はここだけ確認できれば十分です。
- いちばん気になっているバッチを1本だけ選ぶ。
- 起動元(crontab・タイマー)を見つけて、実行時刻・ユーザー・引数をメモする。
- ログか更新日時で、最近ちゃんと動いているかを確かめる。
- わかる範囲で出力(書き換えているもの)を書き出す。
ここまでで30分〜1時間ほど。④のソースの拾い読みとカルテ作りは、別の日に回してかまいません。
正体不明のバッチ 解読チェックリスト
全部に○が付かなくても大丈夫です。わかったところから埋めていきましょう。
起動と実行
- 起動元(crontab・
/etc/cron.d/・systemdタイマーなど)を特定したか - 実行時刻・実行ユーザー・引数をメモしたか
- ログや実行記録で、最近正常に終わっていることを確かめたか
入力と出力
- 読み込んでいるファイル・テーブル・外部データを書き出したか
- 書き換えているテーブル・ファイルを書き出したか
- 外部への送信(ファイル転送・API・メール)があるか確かめたか
- 削除処理(
rm・DELETE・TRUNCATE・古いファイルの掃除)があるか確かめたか
判断と記録
- 出力を使っている人・部署・後続処理を挙げたか
- 本番で試しに手動実行していないか(確かめるなら検証環境で)
- 「止めたら何が起きるか」を1文で言えるか
- わかったこと・わからないことをバッチカルテに残したか
よければ、こちらも
正体不明のバッチの解読は、引き継ぎや仕様の掘り起こしとひと続きの作業です。あわせて読むと、調べたことが資産として残りやすくなります。
- cron・常駐プロセスの棚卸し手順|何が自動で動いているか把握する:解読する前に、サーバー全体で何が動いているかを一覧にする方法です。
- cronバッチの失敗に気づく仕組み|静かに止まるジョブを見逃さない:正体がわかったバッチを、止まったらすぐ気づける状態にします。
- 仕様書がないシステムの仕様を、現状から起こす進め方:バッチカルテを、システム全体の仕様の掘り起こしにつなげる進め方です。
- 作った人がいないシステムを引き継いだ初日にやること:引き継ぎ直後に、どこから手をつけるかの全体像です。
- サーバー・サービス構成を1枚にまとめる方法:バッチの入出力を、構成図の中に位置づけるときに。

正体のわからないものを毎晩動かし続けるのは、思っている以上に気を張る仕事です。それでも今日まで止めずに守ってきたこと自体が、もう立派な保守です。 まずは1本だけ、起動元とログを見てみてください。正体がひとつわかるたびに、そのシステムは「触れないもの」から「自分が守れるもの」に変わっていきます。
ほかの実務ヒントは記事一覧からどうぞ。保守運用の小さな備えを、メールでも少しずつお届けしています。