お世話になっております。
Raspberry Pi4にて、センサー制御とデータ取得のシステムを作成しています。
今回、教えていただきたいのは、タイトルのとおりで、
「無限ループ(待機)中の親プロセスから、トリガーによって呼び出された子プロセスを、親プロセスを終了させることなく、正常に終了させる方法」
です。
前提・実現したいこと
OS:Raspbian Buster
使用言語:python3.7、bash
ラズパイに複数センサーを接続し、そのデータを取得しています。
/etc/rc.localにbutton_rec.pyを追加して、起動時に実行されるようにしています。
start.shはGPIOピンに繋がったボタンの挙動を監視しており、
特定のボタンが押されると、start.shがセンサーを起動させ、そのデータをファイルに記述していき、stop.shで止める、ということが実現したいです。
ファイル配下の通りです。
button_rec.py ┣ start.sh ┃ ┣ sensor1(C++) ┃ ┗ sensor2.py ┗ stop.sh
前述したとおり、
- button_rec.pyはラズパイ起動時に自動起動しGPIOの状態を監視
- スタート用ボタンの押下で、start.shを呼び出す
- start.shはsensor1とsensor2.pyをバックグラウンドで実行させ、データを取得
- ストップ用ボタンの押下で、stop.shを呼び、sensor1とsensor2.pyを終了させる
という流れを期待しています。
- ここで、sensor1とsensor2.pyはそれぞれ単体では機能しています。
また、当然ですが、それぞれを単体で呼び出したとき、Ctrl+C
、あるいはkill -2 PID
で終了させても、期待通りにデータのログファイルは生成・記録されます。
- start.shで呼び出した後、手動およびstop.shでsensor1、sensor2.pyを終了させると、データのログファイルは生成されるも、データが記録されません。
主なコードは以下のとおりです。
python
1#!/usr/bin/python3 2# -*- coding:utf-8 -*- 3 4import RPi.GPIO as GPIO 5import time 6import sys, os 7import ViewMessage as vm 8 9if __name__ == "__main__": 10 11 vm.set_HelloMsg() 12 13 try: 14 pin_start = 15 15 pin_stop = 23 16 17 GPIO.setmode(GPIO.BCM) 18 GPIO.setup(pin_start, GPIO.IN, pull_up_down = GPIO.PUD_UP) 19 GPIO.setup(pin_stop, GPIO.IN, pull_up_down = GPIO.PUD_UP) 20 21 while True: 22 button_blue = GPIO.input(pin_start) 23 button_yellow = GPIO.input(pin_stop) 24 25 cmd = "" 26 if button_blue == False: 27 GPIO.cleanup() 28 os.system("/home/pi/project/src/start.sh") 29 elif button_yellow == False: 30 GPIO.cleanup() 31 os.system("/home/pi/project/src/stop.sh") 32 if cmd != "": 33 ret = os.popen(cmd).readline().strip() 34 print(ret) 35 time.sleep(1) 36 37 time.sleep(1) 38 39 GPIO.cleanup() 40 41 except KeyboardInterrupt: 42 GPIO.cleanup() 43 sys.exit()
bash
1#!/bin/bash 2 3/home/pi/project/src/sensor1 > /home/pi/project/temp/"`date +%Y%m%d_%H%M%S`"_sensor1.txt & 4python /home/pi/project/src/sensor2.py > /home/pi/project/temp/"`date +%Y%m%d_%H%M%S`"_sensor2.txt &
bash
1#!/bin/bash 2 3PID=`pgrep start.sh` 4PIDS[0]=`pgrep python -n` 5PIDS[1]=`pgrep sensor1` 6 7echo $PID 8echo ${PIDS[0]} 9echo ${PIDS[1]} 10 11echo `sudo kill -2 -${PIDS[0]}` 12echo `sudo kill -2 -${PIDS[1]}`
試したこと
運用時のままの構成とプログラムでは問題がわかりにくいかと思い、以下のような構成でテストを行いました。
start.sh ┣ test1.py ┗ test2.py
コードは以下のとおりです。
bash
1# start.sh 2#!/bin/bash 3 4/usr/bin/python3 test1.py & 5/usr/bin/python3 test2.py & 6 7while :; 8do 9 echo "Now running..." 10 sleep 5 11done
python
1# test1.py 2#!/usr/bin/python3 3# -*- coding:utf-8 -*- 4 5import time 6import sys, os 7 8BASE_DIR = './' 9 10try: 11 path = BASE_DIR + "test1.txt" 12 with open(path, mode='w') as f: 13 while True: 14 msg = "Hello\n" 15 #print(msg) 16 f.write(msg) 17 time.sleep(1) 18 19except KeyboardInterrupt: 20 print("end") 21 #sys.exit() 22 os._exit(0)
python
1# test2.py 2#!/usr/bin/python3 3# -*- coding:utf-8 -*- 4 5import time 6import sys, os 7 8BASE_DIR = "./" 9try: 10 path = BASE_DIR + "test2.txt" 11 with open(path, mode="w") as f: 12 msg = "World!\n" 13 while True: 14 #print(msg) 15 f.write(msg) 16 time.sleep(1) 17 18except KeyboardInterrupt: 19 print("end") 20 #sys.exit() 21 os._exit(0)
実運用のものとの違いとしては、
- よびだされるプログラムがこちらは両方共pythonのもの。
- リダイレクトでファイルに記述していた出力を、python内で行う。
この構成でいくつかパターンを変えて実行しました。
- test1.pyまたはtest2.pyのみ実行
- start.shを実行
この時、1のパターンでは、kill -2 PID
ではファイルが作成されますが、kill -KILL PID
ではされませんでした。(このあたりは自明なのかもしれませんが、Linuxやシステムの知識が乏しいため、わかりませんでした)
2のパターンでは先にtest1.py、test.2.pyをkillしても、start.shをkillしてもファイルは作られても、記述はされませんでした。
タイトル、および冒頭に記述した通り、** start.shを止めることなく、ファイル作成・記述を行って二つの子プロセスを止める方法**はありますでしょうか?
よろしくお願いいたします。
回答2件
あなたの回答
tips
プレビュー