<h3 class="post-title entry-title" itemprop="name" style="margin: 0.75em 0px 0px; position: relative; font-variant-numeric: normal; font-variant-east-asian: normal; font-weight: normal; font-stretch: normal; font-size: 22px; line-height: normal; font-family: Arial, Tahoma, Helvetica, FreeSans, sans-serif; color: #222222; background-color: #ffffff;">라즈베리 파이에서 systemd를 사용해 부팅시 프로그램을 자동 실행 (Execute script on boot using systemd)</h3>
<div class="post-header" style="line-height: 1.6; margin: 0px 0px 1.5em; font-size: 10.8px; color: #222222; font-family: Arial, Tahoma, Helvetica, FreeSans, sans-serif; background-color: #ffffff;">
   <div class="post-header-line-1">&nbsp;</div>
   </div>
<div class="post-body entry-content" id="post-body-945932860221867045" itemprop="description articleBody" style="width: 700px; font-size: 13.2px; line-height: 1.4; position: relative; color: #222222; font-family: Arial, Tahoma, Helvetica, FreeSans, sans-serif; background-color: #ffffff;">
   <div class="separator" style="clear: both; text-align: center;"><a href="https://1.bp.blogspot.com/-DODaOXicO_g/VzU9nl0YPWI/AAAAAAAAE_4/rxezyFiuFfskuBGaX693LNznX9QBud_jQCLcB/s1600/EB729FC7-D8ED-4317-8611-9BCBD9CEB8C4.png" imageanchor="1" style="text-decoration-line: none; color: #7c93a1; margin-left: 1em; margin-right: 1em;" target="_blank"><img border="0" height="306" src="https://1.bp.blogspot.com/-DODaOXicO_g/VzU9nl0YPWI/AAAAAAAAE_4/rxezyFiuFfskuBGaX693LNznX9QBud_jQCLcB/s640/EB729FC7-D8ED-4317-8611-9BCBD9CEB8C4.png" width="640" style="border: 1px solid rgb(238, 238, 238); position: relative; padding: 5px; background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial; box-shadow: rgba(0, 0, 0, 0.1) 1px 1px 5px;" /></a></div>
   <br /><br /><br />
   <div style="font-family: &quot;Helvetica Neue&quot;; font-size: 14px;">Raspbian 최신버젼이 릴리즈 되면서 cron이나 rc.local을 사용해 파이선 스크립트를 부팅시 자동실행 시키는 데서 고생하기 시작하였다. Raspbian의 부트 순서가 변경되어 이 프로세스들이 다른 시점에서 실행되기 때문인 것으로 보인다. 이것이 얼마나 문제가 되는지는 실행할 파이선 스크립트가 어떤 일을 하고 어떤 리소스를 필요로 하는가에 따라 치명적일 수도 있고 별 문제가 되지 않을 수도 있다.</div>
   <div style="font-family: &quot;Helvetica Neue&quot;; font-size: 14px;"><br /></div>
   <div style="font-family: &quot;Helvetica Neue&quot;; font-size: 14px;">부팅시 실행될 파이선 스크립트가 실행 시점에서 어떤 시스템 기능을 필요로 한다면 이 문제는 매우 치명적이다. 일반적으로 다음과 같은 것들이 포함된다.</div>
   <div style="font-family: &quot;Helvetica Neue&quot;; font-size: 14px;">&nbsp;</div>
   <ul style="padding: 0px 2.5em; margin: 0.5em 0px; line-height: 1.4; font-family: &quot;Helvetica Neue&quot;; font-size: 14px;">
      <li style="padding: 0px; margin: 0px 0px 0.25em;">네트웍이 연결되어 있어야 함</li>
      <li style="padding: 0px; margin: 0px 0px 0.25em;">/home/pi 디렉토리가 마운트 되어 읽을 수 있어야 함</li>
      <li style="padding: 0px; margin: 0px 0px 0.25em;">시스템의 시간이 NTP로 업데이트 되어야 함</li>
      </ul>
   <div style="font-family: &quot;Helvetica Neue&quot;; font-size: 14px;">&nbsp;</div>
   <div style="font-family: &quot;Helvetica Neue&quot;; font-size: 14px;">그래서 커스텀 기능을 실행시키는데 권자오디는 방법이라 여려 리눅스 패키지에서 적용하고 있는 ’systemd’를 사용하기로 했다. systemd는 리눅스 시스템의 설정을 관리하기 위한 소프트웨어 툴로 이전에 동일한 목적으로 사용되던 여러 툴들을 대체하기 위한 목적으로 만들어 졌다.</div>
   <div style="font-family: &quot;Helvetica Neue&quot;; font-size: 14px;"><br /></div>
   <div style="font-family: &quot;Helvetica Neue&quot;; font-size: 14px;">systemd는 각자의 수준에 따라 매우 쉽거나 또는 매우 공포스러울 수 있다. 여기서는 최소한의 수고로 단지 스크립트 하나를 실행되도록 하는것이 목표이다.</div>
   <div style="font-family: &quot;Helvetica Neue&quot;; font-size: 14px;"><br /></div>
   <div style="font-family: &quot;Helvetica Neue&quot;;"><span style="font-size: large;">Step 1 - 파이선 스크립트</span></div>
   <div style="font-family: &quot;Helvetica Neue&quot;; font-size: 14px;">&nbsp;</div>
   <div style="font-family: &quot;Helvetica Neue&quot;; font-size: 14px;">여기서 사용할 예제 스크립트는 /home/pi 디렉토리에 저장되어 있고 이름은 ‘myscript.py’이다. &nbsp;</div>
   <div style="font-family: &quot;Helvetica Neue&quot;; font-size: 14px;"><br /></div>
   <div style="font-family: &quot;Helvetica Neue&quot;;"><span style="font-size: large;">Step 2 - Unit 파일 만들기</span></div>
   <div style="font-family: &quot;Helvetica Neue&quot;; font-size: 14px;">&nbsp;</div>
   <div style="font-family: &quot;Helvetica Neue&quot;; font-size: 14px;">다음으로 해야 할 일은 설정 파일(aka Unit file)을 만들어 systemd에게 언제 무엇을 해야 하는지 알려줘야 한다.</div>
   <div style="font-family: &quot;Helvetica Neue&quot;; font-size: 14px;"><br /></div>
   <div style="font-family: &quot;Helvetica Neue&quot;; font-size: 14px;"><span style="font-family: &quot;Courier New&quot;;">$&nbsp;<b>sudo vi /lib/systemd/system/myscript.service</b></span></div>
   <div style="font-family: &quot;Helvetica Neue&quot;; font-size: 14px;"><br /></div>
   <div style="font-family: &quot;Helvetica Neue&quot;; font-size: 14px;">에디터를 실행한 다음 아래의 내용을 입력한다.</div>
   <div style="font-family: &quot;Helvetica Neue&quot;; font-size: 14px;"><br /></div>
   <div style="font-family: &quot;Helvetica Neue&quot;; font-size: 14px;"><span style="font-family: &quot;Courier New&quot;;">[Unit] Description=My Script Service</span></div>
   <div style="font-family: &quot;Helvetica Neue&quot;; font-size: 14px;"><span style="font-family: &quot;Courier New&quot;;">After=multi-user.target</span></div>
   <div style="font-family: &quot;Helvetica Neue&quot;; font-size: 14px;"><span style="font-family: &quot;Courier New&quot;;"><br /></span></div>
   <div style="font-family: &quot;Helvetica Neue&quot;; font-size: 14px;"><span style="font-family: &quot;Courier New&quot;;">[Service]</span></div>
   <div style="font-family: &quot;Helvetica Neue&quot;; font-size: 14px;"><span style="font-family: &quot;Courier New&quot;;">Type=idle</span></div>
   <div style="font-family: &quot;Helvetica Neue&quot;; font-size: 14px;"><span style="font-family: &quot;Courier New&quot;;">ExecStart=/usr/bin/python /home/pi/myscript.py</span></div>
   <div style="font-family: &quot;Helvetica Neue&quot;; font-size: 14px;"><span style="font-family: &quot;Courier New&quot;;"><br /></span></div>
   <div style="font-family: &quot;Helvetica Neue&quot;; font-size: 14px;"><span style="font-family: &quot;Courier New&quot;;">[Install]</span></div>
   <div style="font-family: &quot;Helvetica Neue&quot;; font-size: 14px;"><span style="font-family: &quot;Courier New&quot;;">WantedBy=multi-user.target</span></div>
   <div style="font-family: &quot;Helvetica Neue&quot;; font-size: 14px;"><br /></div>
   <div style="font-family: &quot;Helvetica Neue&quot;; font-size: 14px;">위의 파일은 “My Script Service”라는 이름의 새 서비스를 정의하고, ‘multi-user’ 환경이 사용 가능해 졌을 때 서비스를 한번만 실행하도록 요구한다. “ExecStart” 파라미터는 실행하길 원하는 명령어를 지정한다. “Type”은 모든 것이 다 로드 된 후에만 ExecStart 명령이 실행되는걸 보장하기 위해 ‘idle’로 설정한다. 예제에 사용한 GPIO 기반의 스크립트는 디폴트인 ‘simple’에서는 동작하지 않는다.&nbsp;</div>
   <div style="font-family: &quot;Helvetica Neue&quot;; font-size: 14px;"><br /></div>
   <div style="font-family: &quot;Helvetica Neue&quot;; font-size: 14px;">파일의 패스는 절대주소여야 하고 스크립트의 위치 뿐 아니고 파이선의 위치까지도 완전히 지정해 줘야만 한다.</div>
   <div style="font-family: &quot;Helvetica Neue&quot;; font-size: 14px;"><br /></div>
   <div style="font-family: &quot;Helvetica Neue&quot;; font-size: 14px;">스크립트의 텍스트 출력을 로그파일에 저장하고 싶으면 ExecStart 라인을 다음과 같이 바꾸면 된다.</div>
   <div style="font-family: &quot;Helvetica Neue&quot;; font-size: 14px;"><br /></div>
   <div style="font-family: &quot;Helvetica Neue&quot;; font-size: 14px;"><span style="font-family: &quot;Courier New&quot;;">ExecStart=/usr/bin/python /home/pi/myscript.py &gt; /home/pi/myscript.log 2&gt;&amp;1</span></div>
   <div style="font-family: &quot;Helvetica Neue&quot;; font-size: 14px;"><br /></div>
   <div style="font-family: &quot;Helvetica Neue&quot;; font-size: 14px;">Unit 파일의 퍼미션은 644로 설정해야 한다.</div>
   <div style="font-family: &quot;Helvetica Neue&quot;; font-size: 14px;"><br /></div>
   <div style="font-family: &quot;Helvetica Neue&quot;; font-size: 14px;"><span style="font-family: &quot;Courier New&quot;;">$&nbsp;<b>sudo chmod 644 /lib/systemd/system/myscript.service</b></span></div>
   <div style="font-size: 14px;"><span style="font-family: &quot;Helvetica Neue&quot;, Arial, Helvetica, sans-serif;"><br /></span></div>
   <div style="font-family: &quot;Helvetica Neue&quot;; font-size: 14px;"><span style="font-size: large;"><span style="font-family: &quot;Helvetica Neue&quot;, Arial, Helvetica, sans-serif;">Step 3 - systemd 설정</span></span></div>
   <div style="font-family: &quot;Helvetica Neue&quot;; font-size: 14px;">&nbsp;</div>
   <div style="font-family: &quot;Helvetica Neue&quot;; font-size: 14px;">unit파일이 정의되었으므로 systemd에게 부팅시 이것을 사용하도록 알려줘야 한다.</div>
   <div style="font-family: &quot;Helvetica Neue&quot;; font-size: 14px;"><br /></div>
   <div style="font-family: &quot;Helvetica Neue&quot;; font-size: 14px;"><span style="font-family: &quot;Courier New&quot;;">$&nbsp;<b>sudo systemctl daemon-reload</b></span></div>
   <div style="font-family: &quot;Helvetica Neue&quot;; font-size: 14px;"><span style="font-family: &quot;Courier New&quot;;">$&nbsp;<b>sudo systemctl enable myscript.service</b></span></div>
   <div style="font-family: &quot;Helvetica Neue&quot;; font-size: 14px;"><br /></div>
   <div style="font-family: &quot;Helvetica Neue&quot;; font-size: 14px;">이제 시스템을 리부트 시키면 myscript.py가 자동으로 실행될 것이다.</div>
   <div style="font-family: &quot;Helvetica Neue&quot;; font-size: 14px;"><br /></div>
   <div style="font-family: &quot;Helvetica Neue&quot;; font-size: 14px;"><span style="font-family: &quot;Courier New&quot;;">$&nbsp;<b>sudo reboot</b></span></div>
   <div style="font-family: &quot;Helvetica Neue&quot;; font-size: 14px;"><br /></div>
   <div style="font-family: &quot;Helvetica Neue&quot;;"><span style="font-size: large;">Step 4 - 서비스 상태 확인</span></div>
   <div style="font-family: &quot;Helvetica Neue&quot;; font-size: 14px;">&nbsp;</div>
   <div style="font-family: &quot;Helvetica Neue&quot;; font-size: 14px;">서버스의 상태는 다음 명령으로 확인해 볼 수 있다.</div>
   <div style="font-family: &quot;Helvetica Neue&quot;; font-size: 14px;"><br /></div>
   <div style="font-family: &quot;Helvetica Neue&quot;; font-size: 14px;"><span style="font-family: &quot;Courier New&quot;;">$&nbsp;<b>sudo systemctl status myscript.service</b></span></div>
   <div style="font-family: &quot;Helvetica Neue&quot;; font-size: 14px;"><span style="font-family: &quot;Courier New&quot;;"><b>====================================================================================================</b></span></div>
   <div style="font-family: &quot;Helvetica Neue&quot;; font-size: 14px;"><span style="font-family: &quot;Courier New&quot;;"><b>&nbsp;</b></span></div>
   <div style="font-family: &quot;Helvetica Neue&quot;; font-size: 14px;">
      <h3 class="post-title entry-title" itemprop="name" style="margin: 0.75em 0px 0px; position: relative; font-variant-numeric: normal; font-variant-east-asian: normal; font-weight: normal; font-stretch: normal; font-size: 22px; line-height: normal; font-family: &quot;Trebuchet MS&quot;, Trebuchet, Verdana, sans-serif; color: #666666;">(raspberry pi) rc.local에 자동 실행되는 프로그램을 등록해도 실행이 안될때</h3>
      <div class="post-header" style="line-height: 1.6; margin: 0px 0px 1.5em; font-size: 10.8px; color: #666666; font-family: &quot;Trebuchet MS&quot;, Trebuchet, Verdana, sans-serif;">
         <div class="post-header-line-1">&nbsp;</div>
         </div>
      <div class="post-body entry-content" id="post-body-5645034669634187954" itemprop="description articleBody" style="width: 546px; font-size: 13.2px; line-height: 1.4; position: relative; color: #666666; font-family: &quot;Trebuchet MS&quot;, Trebuchet, Verdana, sans-serif;">증상: 제가 만들었던 프로그램은 db에 연결해서 1분마다 db데이터를 체크하는 프로그램이었습니다. 이 프로그램을 rc.local에 등록해서 라즈베리파이가 부팅될 때 실행되고, 해당 프로그램은 while문으로 무한반복되는 구조였습니다. 그런데 rc.local에 등록해도 백그라운드로 실행되지 않는 문제가 발생했습니다.<br /><br />해결: rc.local에 추가한 프로그램이 작동되는지 여부를 확인하기 위해 test.py 프로그램을 작성해서 입력했습니다.<br />- test.py<br /><br />import time<br />while True:<br />&nbsp; &nbsp; &nbsp; &nbsp;time.sleep(60)<br /><br />-rc.local에 추가한 사항<br />&nbsp; &nbsp; python /var/www/html/test.py &amp;<br /><br /><br />확인결과, 정상작동 했습니다. 일단, rc.local에 등록된 프로그램은 실행된다는 것이었고, sleep 60초를 걸어놓은 무한루프 프로그램도 잘 동작한다는 결과를 도출했습니다.<br />그래서 문제의 원인이 뭔지를 고민하던 차에, raspberry pi를 재부팅하고 웹페이지를 요청할 때, html 코드는 정상적으로 출력되지만, mysql db에 연결해서 데이터 로드하는 부분은 'mysql이 연결되지 않았습니다' 와 같은 메시지가 출력되는것에 착안해서, mysql에 연결해서 로드하는 부분을 try 부분에 넣고 except 부분에는 time.sleep(60)을 넣고, else 부분은 return을 넣고 무한루프를 돌렸습니다.<br />mysql를 연결 및 데이터 로드를 시도해보고, 오류 발생시 sleep 60초가 실행되고 60초 후에 다시 시도합니다. 그리고 연결 및 데이터 로드가 완료되면, return되어 db 데이터 로드 로직이 완료됩니다.<br /><br />-get.py(예제)<br /><br />import MySQLdb<br />import time<br /><br />def getTimetable():<br />&nbsp; &nbsp; while True:<br />&nbsp; &nbsp; &nbsp; &nbsp; try:<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; db 연결 및 데이터 로드 로직<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; db_record = 로드된 db 데이터<br />&nbsp; &nbsp; &nbsp; &nbsp; except:<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; time.sleep(60)<br />&nbsp; &nbsp; &nbsp; &nbsp; else:<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return db_record</div>
      <span style="font-family: &quot;Courier New&quot;;"></span></div>
   </div>