msqllibを使用するプログラムがあります。私が作成したいくつかのハードウェアをスキャンしてからmysqlデータベースを更新します。このプログラムは長年実行されてきましたが、システムの再起動時に自動的に起動できませんでした。これで、制御できない電源循環の問題が発生し、自動的に実行されるようにしたいと思います。
rc.localには次のものがあります。
#!/bin/sh -e
#
# rc.local
#
# This script is executed at the end of each multiuser runlevel.
# Make sure that the script will "exit 0" on success or any other
# value on error.
#
# In order to enable or disable this script just change the execution
# bits.
#
# By default this script does nothing.
# Print the IP address
_IP=$(hostname -I) || true
if [ "$_IP" ]; then
printf "My IP address is %s\n" "$_IP"
fi
/home/nigel/scan
exit 0
コマンドプロンプトでコードを入力してデータベースを更新すると、コードが正しく実行されます。ただし、rc.localに入れると、次のように ps -ef
表示されます。
root 356 350 0 20:54 ? 00:00:03 /home/nigel/scan
ただし、プログラムはデータベースを更新するためにSQL呼び出しを実行しません。
rc.localの状態について尋ねる場合:
root@Pi-Scan:~# systemctl status rc-local.service
● rc-local.service - /etc/rc.local Compatibility
Loaded: loaded (/lib/systemd/system/rc-local.service; enabled-runtime; vendor preset: enabled)
Drop-In: /usr/lib/systemd/system/rc-local.service.d
└─debian.conf
/etc/systemd/system/rc-local.service.d
└─ttyoutput.conf
Active: activating (start) since Sat 2023-05-06 20:54:19 EDT; 12min ago
Docs: man:systemd-rc-local-generator(8)
Cntrl PID: 350 (rc.local)
Tasks: 2 (limit: 414)
CPU: 3.903s
CGroup: /system.slice/rc-local.service
├─350 /bin/sh -e /etc/rc.local start
└─356 /home/nigel/scan
May 06 20:54:21 Pi-Scan rc.local[356]: error: first parameter is not a valid address family: Transport endpoint is not connected
May 06 20:54:22 Pi-Scan rc.local[356]: error: first parameter is not a valid address family: Transport endpoint is not connected
May 06 20:54:23 Pi-Scan rc.local[356]: error: first parameter is not a valid address family: Transport endpoint is not connected
May 06 20:54:24 Pi-Scan rc.local[356]: error: first parameter is not a valid address family: Transport endpoint is not connected
May 06 20:54:25 Pi-Scan rc.local[356]: error: first parameter is not a valid address family: Transport endpoint is not connected
May 06 20:54:26 Pi-Scan rc.local[356]: error: first parameter is not a valid address family: Transport endpoint is not connected
May 06 20:54:27 Pi-Scan rc.local[356]: error: first parameter is not a valid address family: Transport endpoint is not connected
May 06 20:54:28 Pi-Scan rc.local[356]: error: first parameter is not a valid address family: Transport endpoint is not connected
systemctl restart rc-local.service
しかし、プログラムの2番目のインスタンスを実行すると正常に動作します!
これが競合状態かもしれないと思ってコマンドの前にスリープ5を追加しようとしましたが、まだ同じ問題が発生しました。
答え1
コメントに注意してください
# This script is executed at the end of each multiuser runlevel.
もはや完全に真実ではないかもしれません。
これは、クラシックSysVinitを使用し、すべての起動スクリプトが厳密に順次実行される場合に当てはまります。ただし、より多くの並列性を追加するために最初のスクリプトを再設計した後、特にSysVinitがsystemdに置き換えられた後、これは保証されませんrc.local
。終わり起動プロセス。
rc-local.service
systemdが起動する必要があることを明示的に指示しない限り後ろにデータベースは実行中で、ネットワークが起動するとすぐに実行されます(通常は/usr/lib/systemd/system/rc-local.service.d/debian.conf
順序制約が適用されますAfter=network-online.target
)。
MySQLデータベースには同じソート制約がある可能性が高いため、rc-local.service
データベースとデータベースが同時に並列に開始され、互いに効果的に競合する可能性が高くなります。データベースを起動するのに5秒以上かかりやすいので(特にRasPiの場合)、レースでrc-local.service
「勝利」し、データベースがまだ完全に実行されていないときにデータベースに接続しようとすることができます。
/home/nigel/scan
エラー処理コードを改善すると役に立ちます。繰り返されるTransport endpoint is not connected
エラーは、プログラムがデータベースへの接続を開こうとしていることを示します。失敗の事実を無視するその後、最初に正常に開かなかった接続を介して一部のデータを転送しようとし続けます。これはすでに失敗する運命です。再試行が必要な主な部分はオープン接続、いいえデータを送る。
答え2
telcoMの優れた回答を拡張するには(IMHOは少なくとも投票して同意する必要があります!):
この問題を解決する最も簡単な方法は、古代のrc.localメカニズムを使用するのではなく、hardware-scan
サービスファイルを生成し、すでに起動されているデータベースサーバーに依存するようにすることです。そうすれば、依存関係が準備されるとすぐに必要な作業が開始されますが、すぐには開始されません。
[Unit]
Description=Scan the hardware using "scan"
# I'm assuming the service is called mariadb.service, but you can check that:
# systemctl status mariadb
# should show it running; if it says that the service couldn't be found,
# try mysql.service instead (I really don't know what you've installed)
After=mariadb.service
[Service]
Type=oneshot
ExecStart=/home/nigel/scan
[Install]
WantedBy=multi-user.target
/etc/systemd/system/に入れて、次の起動時に起動するにはhardware-scan.service
実行してください。sudo systemctl enable hardware-scan
ルートとして実行されることに注意してください!