WSL2環境でCronを実行してみる

Programming
スポンサーリンク

こんにちは、しょうぞうです。

本日は、WSL2環境でCronを実行してみたいと思います。

やりたいこととしては、echo Hello worldをCronで実行できるかどうかです。
本当はもっとちゃんとしたshellscriptを実行しようと考えていたのですが、最初はタスクの粒度を小さくすることにしました。

WSL2のディストリビューションではUbuntuをインストールしています。
バージョンは以下の通り

cat /etc/os-release

PRETTY_NAME="Ubuntu 22.04.1 LTS"
NAME="Ubuntu"
VERSION_ID="22.04"
VERSION="22.04.1 LTS (Jammy Jellyfish)"
VERSION_CODENAME=jammy
ID=ubuntu
ID_LIKE=debian
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
UBUNTU_CODENAME=jammy
スポンサーリンク

スクリプトの作成

まずは、hello worldのshellがちゃんと通常実行できるかを確認します。

とその前にふと思ったのですが、cronで実行するshellってどこに置いておくのが普通なんでしょうかね?
調べてみると/home/username/scriptsなどの下に入れると良いと書いていたので

shozo1030@DESKTOP-A39U63S:~$ mkdir scripts
shozo1030@DESKTOP-A39U63S:~$ cd scripts/
shozo1030@DESKTOP-A39U63S:~/scripts$ touch helloWorld.sh
shozo1030@DESKTOP-A39U63S:~/scripts$ vi helloWorld.sh
shozo1030@DESKTOP-A39U63S:~/scripts$ cat helloWorld.sh
echo "hello world"
shozo1030@DESKTOP-A39U63S:~/scripts$ source helloWorld.sh
hello world
shozo1030@DESKTOP-A39U63S:~/scripts$

とりあえず、helloworldの実行スクリプトは完成しました。

スポンサーリンク

crontab -eで登録

次に、実際に対象のスクリプトをcrontab -eで登録してみて実行できるかどうかを確認します。

crontab -eを実行すると以下のような画面が表示されてvimで登録することができます。
初回の際は、エディタ選択やらなんやらありましたがそこらへんは割愛します。

crontabの時間指定の書き方は以下の通りなので、とりあえず確認したいので1分ごとに実行してもらうようにしてみます。

分 時 日 月 曜日
* * * * *

1 * * * * /home/shozo1030/scripts/helloWorld.sh

こんな感じで書いてみました。果たして実行できるか?

1分経ってもCronは実行されず・・・
何が原因か分析する。

そもそもCronは起動しているか?

cronが起動しているかどうかを確認してみます。

shozo1030@DESKTOP-A39U63S:~/scripts$ sudo service cron status
[sudo] password for shozo1030:
Sorry, try again.
[sudo] password for shozo1030:
* cron is not running
shozo1030@DESKTOP-A39U63S:~/scripts$

cron起動してませんでした・・・
wsl2だとデフォルトでCron起動していないのでしょうか?
ググって起動コマンドを実行したところ以下のエラーが出ました。

shozo1030@DESKTOP-A39U63S:~/scripts$ sudo systemctl start cron
System has not been booted with systemd as init system (PID 1). Can't operate.
Failed to connect to bus: Host is down
shozo1030@DESKTOP-A39U63S:~/scripts$

調べるとsystemdをtrueにしないといけないっぽいのでコンフィグファイルに追記する

shozo1030@DESKTOP-A39U63S:~/scripts$ sudo vi /etc/wsl.conf

その後wslをシャットダウンして再起動してコマンドを打ってみるが同じエラー・・・

shozo1030@DESKTOP-A39U63S:/mnt/c/Users/shozo$ sudo systemctl start cron
System has not been booted with systemd as init system (PID 1). Can't operate.
Failed to connect to bus: Host is down

先ほどCronが起動しているかどうかのコマンドでserviceを使用していたのでserviceで起動してみる

shozo1030@DESKTOP-A39U63S:/mnt/c/Users/shozo$ sudo service cron start
* Starting periodic command scheduler cron [ OK ]
shozo1030@DESKTOP-A39U63S:/mnt/c/Users/shozo$

shozo1030@DESKTOP-A39U63S:/mnt/c/Users/shozo$ sudo service cron status
* cron is running
shozo1030@DESKTOP-A39U63S:/mnt/c/Users/shozo$

cronは動いているようだが、helloWorld.shは実行されない・・・なぜなのか?
ChatGPTに聞いたら以下のように回答されました。
時間指定のやり方が間違っていました・・・

1 * * * * /home/shozo1030/scripts/helloWorld.sh このようにcrontabには書いているのですが、あってますか?
 
ChatGPT
ChatGPT

指定したCronの設定 1 * * * * /home/shozo1030/scripts/helloWorld.sh は、毎時間の1分にスクリプトを実行するように設定しています。つまり、1:01, 2:01, 3:01… というように、各時間の1分に実行されます。

もし1分おきにスクリプトを実行したい場合は、設定を以下のように変更する必要があります:

bash

* * * * * /home/shozo1030/scripts/helloWorld.sh

この設定で、毎分0秒にスクリプトが実行されます。これで問題が解決するかご確認ください。

さらにChatGPTに質問したところ、以下のようにコンソールに表示されないそうなのでログファイルに出力させるようにしました。

Cronジョブは通常、ユーザーがログインしているコンソールやターミナルに出力を表示しません。Cronはバックグラウンドで動作し、スクリプトの標準出力や標準エラー出力はどこにも表示されないため、特定の出力先にリダイレクトする必要があります。

出力のハンドリング:

  1. ファイルへのリダイレクト: スクリプトの出力をファイルにリダイレクトすることで、後で確認することができます。たとえば、次のようにCron設定を行います。

    bash

    * * * * * /home/shozo1030/scripts/helloWorld.sh >> /home/shozo1030/logs/helloWorld.log 2>&1

    この設定では、標準出力と標準エラー出力の両方を helloWorld.log に追記します。

2>&1の意味

1は標準出力2は標準エラー出力
つまり標準エラー出力を標準出力にリダイレクトしていることを意味しています。
これによりエラーメッセージが標準出力と同じ場所に送られることでコンソールに表示することができるというわけです。

話は戻って、

上記のようにcrontab -eの内容を変更したのちに、logsフォルダとhelloWorld.logを作成しました。
その後、tailコマンドで追記されているかどうかを確認したところ以下のようになりました。

Permission deniedになっている!!!!
けどとりあえずcronがしっかり実行されているところまでは行けた!
あとは実行権限を付与してあげればよさそう。

実行権限を以下のように付与します。

以下ChatGPTによる説明

実行権限の付与について

Crontab自体に直接実行権限を付与するというよりは、Cronで実行するスクリプトに実行権限を付与する必要があります。ここでは、Cronで実行するスクリプトファイルに実行権限を付与する方法について説明します。

### スクリプトに実行権限を付与する手順

1. **ターミナルを開く**: ターミナルまたはコマンドラインインターフェイスを開きます。

2. **スクリプトの場所に移動**: `cd` コマンドを使って、スクリプトが保存されているディレクトリに移動します。例えば、スクリプトが `/home/username/scripts` ディレクトリにある場合は、以下のコマンドを実行します。
“`bash
cd /home/username/scripts
“`

3. **実行権限を付与**: `chmod` コマンドを使用してスクリプトに実行権限を付与します。スクリプト名が `helloWorld.sh` である場合、以下のコマンドを実行します。
“`bash
chmod +x helloWorld.sh
“`

このコマンドにより、スクリプトは実行可能になります。

### 注意点
– **パスの確認**: スクリプトをCronジョブとして追加する際には、スクリプトのフルパスを正確に指定することが重要です。`which` コマンドを使ってコマンドのフルパスを確認することができます。
– **Cronの環境**: Cronジョブは限定的な環境変数セットで実行されるため、スクリプト内で必要な環境変数を設定するか、使用するコマンドのフルパスを指定する必要があります。
– **ログの確認**: Cronジョブの実行結果を確認するために、出力をログファイルにリダイレクトすると良いでしょう。

以上の手順でスクリプトに実行権限を付与し、Cronジョブとして問題なく実行できるようになります。

+xの意味

`+x` はUNIXおよびUNIX系オペレーティングシステムのファイルシステムにおける権限設定の一部で、特定のファイルに「実行権限」を追加することを意味します。`chmod` コマンドを使用してこの設定を行います。

### `chmod` コマンドの概要

`chmod` は “change mode” の略で、ファイルやディレクトリのアクセス権限を変更するために使用されます。アクセス権限には以下の三つがあります:

– **読み取り権限 (r)**: ファイルの内容を読むことができる権限。
– **書き込み権限 (w)**: ファイルの内容を変更することができる権限。
– **実行権限 (x)**: ファイルをプログラムやスクリプトとして実行することができる権限。

### 実行権限 (`x`) の意味

ファイルに対する `+x` の指定は、そのファイルを実行可能なプログラムまたはスクリプトとして扱えるようにするためのものです。通常、シェルスクリプトやコンパイル済みのプログラムファイルに対して実行権限を付与します。

### 使用例

例えば、`helloWorld.sh` という名前のシェルスクリプトファイルに実行権限を付与する場合、以下のコマンドを使用します:

“`bash
chmod +x helloWorld.sh
“`

このコマンドは `helloWorld.sh` に実行権限を追加します。これにより、ユーザーはスクリプトファイルを直接実行することが可能になります(例: `./helloWorld.sh`)。

### 権限の確認

ファイルの現在の権限を確認するには、`ls -l` コマンドを使用します。このコマンドはファイルの権限を含む詳細なリストを表示します。例えば、

“`bash
ls -l helloWorld.sh
“`

出力例:

“`plaintext
-rwxr-xr-x 1 user group 28 Oct 18 12:00 helloWorld.sh
“`

ここで、`rwxr-xr-x` という部分がファイルの権限を表しており、最初の `rwx` はファイルの所有者に対する読み取り、書き込み、実行の権限があることを示しています。

再度、logファイルを見てみる

ちゃんとログが表示されている!
地味に色々調べてめんどくさかったけど、無事に成功しました!

systemctlでは動かなくてserviceでは動く

この原因は何でなのか?気になったので調べました。

`systemctl`と`service`コマンドは、Linuxシステムでサービスを管理するためのツールですが、それぞれ異なるシステムに基づいています。

1. **systemctl**
– `systemctl`は`systemd`システムの一部で、現代のほとんどのLinuxディストリビューションで採用されている初期化システムです。
– `systemd`は従来のSysV initスクリプトに代わるものとして導入されました。
– `systemctl`を使用すると、ユニットファイルという設定ファイルを通じてサービスを有効化、無効化、開始、停止、再起動、ステータス確認などができます。
– マルチユーザー環境や依存関係のあるサービスの管理に優れており、より詳細なコントロールが可能です。

2. **service**
– `service`コマンドは、より古いSysV initスタイルのサービス管理を行いますが、多くの現代のディストリビューションでも後方互換性のためにサポートされています。
– このコマンドはスクリプトを直接操作してサービスを開始、停止、再起動します。
– `service`コマンドは`systemd`が主流になる前の古いディストリビューションで広く使用されていました。
– `service`コマンドの使用は、直感的な操作ではありますが、`systemd`の提供する機能や細かな設定オプションに比べると限定的です。

要約すると、`systemctl`は`systemd`に基づいた現代的な管理方法を提供し、`service`は古いSysV initシステムに基づいた管理方法を提供しますが、多くのシステムで後方互換性のために依然として利用可能です。

これだけだとまだ深くわからないので今度調べてみます!

以上です。参考にしてみてください!

コメント

タイトルとURLをコピーしました