前提
なぜかこの記事は準備編と別れています.前編はこちら
さて,私の環境は
- WSL, Ubuntu22.04.1
となっています.他の環境だとどうなるかは正直わかりません.
daemonにする流れは以下を参考にしています.
discord botのプログラムにShebangを仕込む
とりあえずプログラムにShebangを仕込んで,実行権限を与えておきます.
#!/usr/bin/env python3
import discord
import os
class MyClient(discord.Client):
def __init__(self, *, intents: discord.Intents):
super().__init__(intents=intents)
async def on_ready(self):
print(f"Logged in as {client.user} (ID: {client.user.id})")
print("------")
intents = discord.Intents.default()
client = MyClient(intents=intents)
client.run(os.getenv("TOKEN"))
$ chmod +x defaultbot.py
続いて,daemonの設定ファイルであるUnitファイルを書いていきます
Unitファイル
pythonプログラムをデーモン化する|Unitに処理を記述しsystemdで実行するという記事を参考にしています.
testbot.service
というUnitファイルを/etc/systemd/system/
に作成し,daemonを作っていきます.
[Unit]
Description = test discord bot daemon
[Install]
WantedBy = multi-user.target
[Service]
EnvironmentFile = /home/user/directory/.env
ExecStart = /home/user/directory/defaultbot.py
[Service]のExecStartに実行したいファイルを絶対パスで指定します.また,環境変数を使用するので,それが書かれたファイルをEnvironmentFileに指定します1.
multi-user.target
ちなみに,WantedByに指定したmulti-user.targetですが,OS起動時にsystemdで行われていることという記事によると,GUIなしのアプリ起動に紐づいたものらしいです.
蛇足ですが中身も一応見れます.まあ見ても私にはなにもわかんないんですけど
$ systemctl cat multi-user.target
# /lib/systemd/system/multi-user.target
# SPDX-License-Identifier: LGPL-2.1-or-later
#
# This file is part of systemd.
#
# systemd is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation; either version 2.1 of the License, or
# (at your option) any later version.
[Unit]
Description=Multi-User System
Documentation=man:systemd.special(7)
Requires=basic.target
Conflicts=rescue.service rescue.target
After=basic.target rescue.service rescue.target
AllowIsolate=yes
これで準備が整いました.準備編は終わったんじゃなかった?
次にdaemonとして認識させましょう.
systemctl
daemonとして認識されているか,および起動や停止,自動実行の設定にはsystemctl
コマンドを利用します.
systemctlのコマンドの詳細については以下の記事を参考にしています.
まずはsystemctl list-unit-files --type service
を使って認識されているか確認しましょう.
というところで,WSLだとおそらくsystemctlが使えねえっていうエラーが出ると思います.PID1にsystemdが設定されてないよ,というエラーです.これの解決方法はこちらの記事に載っています.WSLのUbuntu上の/etc/wsl.conf
に
[boot]
systemd=true
を記述し,WSLを再起動させるとできるようになります.wsl.confについてはこちらを見てください.
ただし,ここでWSLをシャットダウンさせて再起動させる際,8秒ほど待たないといけません.詳しくは公式のドキュメントを見てください.
というわけでこれでsystemctl
が使えると思います.試してみてtestbot.service
が表示されるか確認しましょう.
$ systemctl list-unit-files --type service | grep testbot
testbot.service disabled enabled
出てきましたね.次はこれを有効にしましょう.
$ sudo systemctl enable testbot.service
Created symlink /etc/systemd/system/multi-user.target.wants/testbot.service → /etc/systemd/system/testbot.service.
できたら後は起動するだけです.
$ sudo systemctl daemon-reload
$ sudo systemctl start testbot.service
$ sudo systemctl status testbot.service
● testbot.service - test discord bot daemon
Loaded: loaded (/etc/systemd/system/testbot.service; enabled; vendor preset: enabled)
Active: active (running) since Sun 2022-12-18 00:40:04 JST; 18s ago
Main PID: 1701 (python3)
Tasks: 3 (limit: 9421)
Memory: 22.8M
...
動きました.やったね.
停止するには,stopさせればいいです.
$ sudo systemctl stop testbot.service
$ sudo systemctl status testbot.service
○ testbot.service - test discord bot daemon
Loaded: loaded (/etc/systemd/system/testbot.service; enabled; vendor preset: enabled)
Active: inactive (dead) since Sun 2022-12-18 00:41:48 JST; 3s ago
Process: 1701 ExecStart=/home/......./defaultbot.py (code=killed, signal=TERM)
Main PID: 1701 (code=killed, signal=TERM)
Dec 18 00:40:04 DESKTOP-CN6AQ4U systemd[1]: Started test discord bot daemon.
Dec 18 00:40:04 DESKTOP-CN6AQ4U defaultbot.py[1701]: [2022-12-18 00:40:04] [INFO ] discord.client: logging in using static token
Dec 18 00:40:05 DESKTOP-CN6AQ4U defaultbot.py[1701]: [2022-12-18 00:40:05] [INFO ] discord.gateway: Shard ID None has connected to Gateway (>
Dec 18 00:41:48 DESKTOP-CN6AQ4U systemd[1]: Stopping test discord bot daemon...
Dec 18 00:41:48 DESKTOP-CN6AQ4U systemd[1]: testbot.service: Deactivated successfully.
Dec 18 00:41:48 DESKTOP-CN6AQ4U systemd[1]: Stopped test discord bot daemon.
これでPCが起動しっぱなしであればdiscord botも起動しっぱなしになりました.
ちなみに蛇足ですが,私の環境だと,
$ explorer.exe .
run-detectors: unable to find an interpreter for /mnt/c/WINDOWS/explorer.exe
windowsのアプリがWSLでが使えなくなりました.
windowsのアプリがWSLで使えない
こちらに載っている解決方法を試したところ,
-
wsl --shutdown
して再起動- 変わらず
-
export DISPLAY="$(/sbin/ip route | awk '/default/ { print $3 }'):0"
to ~/.bashrc
and‘ sourced it and$ source ~/.bashrc
-
sudo update-binfmts --disable cli
- 上2つを同時に実行
- 使えるようになったけど,再起動で再び使えなくなる
-
[interop]
でappendWindowsPath = true
にする- 変わらず
で変わりませんでした.[automount]
の設定が怪しい気がしたので消してみましたが変わらずです.
解決策はwsl.conf
で[boot]
のsystemd=true
を削除すると使えるようになります.本末転倒ですね.
調べた結果....わかりませんでした!
いかがでしたか?
以上となります.daemon起動の流れを紹介しました.
-
itohalってやつが書いた環境変数の記事では
.profile
に環境変数を設定することができるらしいので,.profile
に環境変数ファイルに指定して起動してみたらうまくいきませんでした.環境変数を認識してくれません.どうして.
.bash_profile
ではうまくいきます.なんで.profile
に環境変数を入れることをおすすめしてるんだ.
ちなみに,.env
で動くのかなと思って試してみたらうまくいったのでそうやってます.
.env
や.bash_profile
と.profile
の違いを考えたとき,性質の違いは置いておいて,exportかなと思います.前者ではtoken="000"
と記述(.bash_profile
ではそこからexport token
)して,.profile
ではexport token="000"
としています.echo
させるとどちらもうまくいきますが,daemonだと前者がうまくいきます.なんでだろ ↩