시작 시 Cron을 사용하여 두 개의 Python 스크립트를 실행해 보세요.

시작 시 Cron을 사용하여 두 개의 Python 스크립트를 실행해 보세요.

crontab파일 에 다음 명령을 넣었습니다 .

@reboot python3 /home/pi/rpi_camera_surveillance_system.py &
@reboot python3 /home/pi/KestrelPi/PIRkestrellogger.py &

첫 번째 스크립트는 제대로 실행되지만 두 번째 스크립트는 그렇지 않습니다. 아래에 두 스크립트를 모두 포함했지만 두 번째 스크립트도 테스트했는데 명령줄에서 호출하면 제대로 작동했습니다.

첫 번째 스크립트:

# Web streaming example
# Source code from the official PiCamera package
# http://picamera.readthedocs.io/en/latest/recipes2.html#web-streaming

import io
import picamera
import logging
import socketserver
from threading import Condition
from http import server

PAGE="""\
<html>
<head>
<title>Kestrel Camera</title>
</head>
<body>
<center><h1>Kestrel Cam</h1></center>
<center><img src="stream.mjpg" width="640" height="480"></center>
</body>
</html>
"""

class StreamingOutput(object):
    def __init__(self):
        self.frame = None
        self.buffer = io.BytesIO()
        self.condition = Condition()

    def write(self, buf):
        if buf.startswith(b'\xff\xd8'):
            # New frame, copy the existing buffer's content and notify all
            # clients it's available
            self.buffer.truncate()
            with self.condition:
                self.frame = self.buffer.getvalue()
                self.condition.notify_all()
            self.buffer.seek(0)
        return self.buffer.write(buf)

class StreamingHandler(server.BaseHTTPRequestHandler):
    def do_GET(self):
        if self.path == '/':
            self.send_response(301)
            self.send_header('Location', '/index.html')
            self.end_headers()
        elif self.path == '/index.html':
            content = PAGE.encode('utf-8')
            self.send_response(200)
            self.send_header('Content-Type', 'text/html')
            self.send_header('Content-Length', len(content))
            self.end_headers()
            self.wfile.write(content)
        elif self.path == '/stream.mjpg':
            self.send_response(200)
            self.send_header('Age', 0)
            self.send_header('Cache-Control', 'no-cache, private')
            self.send_header('Pragma', 'no-cache')
            self.send_header('Content-Type', 'multipart/x-mixed-replace; boundary=FRAME')
            self.end_headers()
            try:
                while True:
                    with output.condition:
                        output.condition.wait()
                        frame = output.frame
                    self.wfile.write(b'--FRAME\r\n')
                    self.send_header('Content-Type', 'image/jpeg')
                    self.send_header('Content-Length', len(frame))
                    self.end_headers()
                    self.wfile.write(frame)
                    self.wfile.write(b'\r\n')
            except Exception as e:
                logging.warning(
                    'Removed streaming client %s: %s',
                    self.client_address, str(e))
        else:
            self.send_error(404)
            self.end_headers()

class StreamingServer(socketserver.ThreadingMixIn, server.HTTPServer):
    allow_reuse_address = True
    daemon_threads = True

with picamera.PiCamera(resolution='640x480', framerate=24) as camera:
    output = StreamingOutput()
    #Uncomment the next line to change your Pi's Camera rotation (in degrees)
    #camera.rotation = 90
    camera.start_recording(output, format='mjpeg')
    try:
        address = ('', 8000)
        server = StreamingServer(address, StreamingHandler)
        server.serve_forever()
    finally:
        camera.stop_recording()

두 번째 스크립트:

# Log motion in Kestrel Box every five seconds in a csv file
import RPi.GPIO as GPIO
import time
import datetime
import csv

GPIO.setwarnings(False)
GPIO.setmode(GPIO.BOARD)
GPIO.setup(11, GPIO.IN)         #Read output from PIR motion sensor
GPIO.setup(3, GPIO.OUT)         #LED output pin

while True:
        i=GPIO.input(11)
        if i==0:                 #When output from motion sensor is LOW
                print ("No motion",i)
                GPIO.output(3, 0)  #Turn OFF LED
                time.sleep(5)
        elif i==1:               #When output from motion sensor is HIGH
                now = datetime.datetime.now()
                GPIO.output(3, 1)  #Turn ON LED
                with open('bird_log.csv', 'a', newline='') as csvfile:
                        logwriter = csv.writer(csvfile, delimiter=',',quotechar='|', quoting=csv.QUOTE_MINIMAL)
                        logwriter.writerow([now.strftime("%Y")] + [now.strftime("%d")] + [now.strftime("%m")] + [now.strftime("%H")] + [now.strftime("%M")] + [now.strftime("%S")] + ["motion"])
                print ([now.strftime("%Y")] + [now.strftime("%d")] + [now.strftime("%m")] + [now.strftime("%H")] + [now.strftime("%M")] + [now.strftime("%S")] + [ "motion"])
                time.sleep(5)

첫 번째 스크립트 외에 시작 시 두 번째 스크립트를 어떻게 실행할 수 있는지 궁금합니다.

답변1

머리말:

cron스크립트가 명령 PATH줄 에서 실행되지만 아래에서는 실행되지 않는 경우리소스 타이밍질문:

1. PATH다른 점:

작업cron확실히동일하게 실행환경대화형 쉘에서 실행되는 명령으로. printenv차이점을 보여줄 수 있습니다:

$ printenv
...
PATH=/home/pi/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin: etc, etc 
...  

이제 파일을 편집하여 실행 하고 출력을 파일로 리디렉션하는 작업을 crontab만듭니다 .cronprintenv

* * * * * /usr/bin/printenv > /home/pi/mycronenvironment.txt 2>&1

당신이 당신의 안에 있다면 crontab당신은 당신의 안에 있다면아니요PATH에서 1) PATH를 변경하거나 2) 명령의 전체 경로를 사용할 수 있습니다.

2. cron자원 가용성을 이해하지 못함

@reboot이는 작업 일정을 잡기 위해 이 시설을 사용할 때 가장 자주 발생합니다. 예를 들어 cron작업이 부팅 시 시작되고 네트워크 서비스가 필요한 경우입니다. 네트워크를 아직 사용할 수 없으면 작업이 실패합니다. 그렇지 않기 때문에인터렉티브, 출력( stdout및/또는 stderr)이 표시되지 않으며 오류 메시지나 경고가 손실될 수 있습니다.

sleep해결책은 일반적으로 명령을 실행하기 전에 무언가를 추가하는 것입니다. 예를 들어:

@reboot /bin/sleep 20; /path/to/myscript >> /pi/home/myscriptlog.txt 2>&1

cron부팅 시 시작 되고 이 줄이 실행되면 다음 명령이 실행되기 전에 20초가 경과 cron됩니다 . sleep이것은 거의 항상 작동하지만 물론부정확하다리소스를 언제 사용할 수 있을지 확신할 수 없기 때문입니다. 귀하의 직업이 이를 요구하거나 이러한 불확실성이 귀하를 괴롭히는 경우,당신은 고려해야systemd;시작하는 동안 시스템 리소스에 대한 가시성을 유지하고 가능한 한 빨리 작업을 시작할 수 있습니다.

cron참고 사항: 기본적으로 실행되는 작업에 대한 오류 메시지/dev/null

이 문제는 위와 같이 수정되었습니다.리디렉션및 "로그 파일" stderr:stdout

>> /home/pi/cronjoboutput.log 2>&1

관련 정보