⏱️

Zennのプレビューと一緒に別の処理を動かす

2024/12/03に公開

ブログ記事を書くとき、色々なスクリプトで自動処理をさせておくと便利です。 例えば簡易的な文章校正をChatGPTで行うなども、定期的にAPIを叩くプログラムを走らせておければ簡単です。 一方、Zenn CLIを使って記事を書く際には、 プレビューのプロセスを起動させながら記事を書いています。 ということで、このプレビューのプロセスに他の機能も相乗りさせることで、 ブログを書くときに意識して起動させるプロセスを一つにすることができます。

これはシェルスクリプトで簡単に実現できました。

スクリプトを書く

期待する動作

  • プレビューを表示する処理に加えて、別の機能も一つのコマンドで実行開始できる。
  • その処理の停止についても、そのプロセスを止めるだけで全ての機能が止まる。

シェルスクリプト

シェルスクリプトはこんな感じでOKでした。

sample.sh
#!/usr/bin/env bash
set -euo pipefail

# プレビューをバックグラウンドで開始
npx zenn preview --open &

# 別の処理
otehr_process &

# プロセスを停止させないようにstdinを待つ
cat

これを単純にそのまま起動します。

bash sample.sh

これだけで、複数の処理を一つのプロセス開始だけで実現でき、 またその停止もCtrl-cで全てが停止されるようになるようです。

最初は難しそうと思ったのですが、 実は、プレビュー実行に&をつけてバックグラウンド処理にするだけでOKでした。

最後のcatについて

&をコマンドの最後につけるとバックグラウンドで処理が開始されます。

バックグラウンド処理は元のプロセス(シェルスクリプトを実行しているプロセス)の子プロセスとして生成されます(実はこれはフォアグラウンド処理も一緒です)。 子プロセスなので、原則として親プロセスが停止されると子プロセスも停止します。

少なくともこれはCtrl-cでプロセスを停止させた時に正常に動作するようです。 しかし親プロセスが正常に終了された場合は、その終了情報は子プロセスには送られないようです。 なので、無限ループを入れるなどしてユーザからの明示的な停止以外ではプロセスを停止させないようにすることで明示的な停止以外で処理が止まらないようにします。

catは標準入力をそのまま出力するコマンドですが、 標準入力がない場合は、それがくるのをずっと待ちます。 よって標準入力がなければ無限に何かを待ち続けるような存在になります。 この方法の方が、無限ループでsleepを入れるより無駄な処理が発生しないはずです。

まとめ

バックグラウンドプロセスを使うことで複数の処理を同時並行して流すことができました。 子プロセスへは、親プロセスのCtrl-cなどの停止命令は伝播されるが、正常終了の情報は伝播されません。 なので親プロセスは明示的な停止命令以外で止まらないようにcatを使う方法を用いました。

以上、誰かの参考になれば幸いです。

GitHubで編集を提案

Discussion