레이블이 부팅시 자동 시작인 게시물을 표시합니다. 모든 게시물 표시
레이블이 부팅시 자동 시작인 게시물을 표시합니다. 모든 게시물 표시

2016년 5월 13일 금요일

라즈베리 파이에서 systemd를 사용해 부팅시 프로그램을 자동 실행 (Execute script on boot using systemd)




Raspbian 최신버젼이 릴리즈 되면서 cron이나 rc.local을 사용해 파이선 스크립트를 부팅시 자동실행 시키는 데서 고생하기 시작하였다. Raspbian의 부트 순서가 변경되어 이 프로세스들이 다른 시점에서 실행되기 때문인 것으로 보인다. 이것이 얼마나 문제가 되는지는 실행할 파이선 스크립트가 어떤 일을 하고 어떤 리소스를 필요로 하는가에 따라 치명적일 수도 있고 별 문제가 되지 않을 수도 있다.

부팅시 실행될 파이선 스크립트가 실행 시점에서 어떤 시스템 기능을 필요로 한다면 이 문제는 매우 치명적이다. 일반적으로 다음과 같은 것들이 포함된다.
  • 네트웍이 연결되어 있어야 함
  • /home/pi 디렉토리가 마운트 되어 읽을 수 있어야 함
  • 시스템의 시간이 NTP로 업데이트 되어야 함
그래서 커스텀 기능을 실행시키는데 권자오디는 방법이라 여려 리눅스 패키지에서 적용하고 있는 ’systemd’를 사용하기로 했다. systemd는 리눅스 시스템의 설정을 관리하기 위한 소프트웨어 툴로 이전에 동일한 목적으로 사용되던 여러 툴들을 대체하기 위한 목적으로 만들어 졌다.

systemd는 각자의 수준에 따라 매우 쉽거나 또는 매우 공포스러울 수 있다. 여기서는 최소한의 수고로 단지 스크립트 하나를 실행되도록 하는것이 목표이다.

Step 1 - 파이선 스크립트
 
여기서 사용할 예제 스크립트는 /home/pi 디렉토리에 저장되어 있고 이름은 ‘myscript.py’이다.  

Step 2 - Unit 파일 만들기
 
다음으로 해야 할 일은 설정 파일(aka Unit file)을 만들어 systemd에게 언제 무엇을 해야 하는지 알려줘야 한다.

$ sudo vi /lib/systemd/system/myscript.service

에디터를 실행한 다음 아래의 내용을 입력한다.

[Unit] Description=My Script Service
After=multi-user.target

[Service]
Type=idle
ExecStart=/usr/bin/python /home/pi/myscript.py

[Install]
WantedBy=multi-user.target

위의 파일은 “My Script Service”라는 이름의 새 서비스를 정의하고, ‘multi-user’ 환경이 사용 가능해 졌을 때 서비스를 한번만 실행하도록 요구한다. “ExecStart” 파라미터는 실행하길 원하는 명령어를 지정한다. “Type”은 모든 것이 다 로드 된 후에만 ExecStart 명령이 실행되는걸 보장하기 위해 ‘idle’로 설정한다. 예제에 사용한 GPIO 기반의 스크립트는 디폴트인 ‘simple’에서는 동작하지 않는다. 

파일의 패스는 절대주소여야 하고 스크립트의 위치 뿐 아니고 파이선의 위치까지도 완전히 지정해 줘야만 한다.

스크립트의 텍스트 출력을 로그파일에 저장하고 싶으면 ExecStart 라인을 다음과 같이 바꾸면 된다.

ExecStart=/usr/bin/python /home/pi/myscript.py > /home/pi/myscript.log 2>&1

Unit 파일의 퍼미션은 644로 설정해야 한다.

$ sudo chmod 644 /lib/systemd/system/myscript.service

Step 3 - systemd 설정
 
unit파일이 정의되었으므로 systemd에게 부팅시 이것을 사용하도록 알려줘야 한다.

$ sudo systemctl daemon-reload
$ sudo systemctl enable myscript.service

이제 시스템을 리부트 시키면 myscript.py가 자동으로 실행될 것이다.

$ sudo reboot

Step 4 - 서비스 상태 확인
 
서버스의 상태는 다음 명령으로 확인해 볼 수 있다.

$ sudo systemctl status myscript.service

2015년 1월 22일 목요일

에디슨에서 부팅할 때 원하는 프로그램을 실행시키기

시스템이 시작할 때 스크립트를 실행하는데는 몇가지 방법이 있다. 하지만 Edison에서 가장 쉬운 방법은 /etc/init.d 디렉토리를 사용하는 것이다. 

만일 init.d를 처음 사용하는 것이면 먼저 이 디렉토리를 만들어야 한다.

$ cd /etc
$ mkdir init.d

이제 만들어 진 디렉토리로 이동한다.

$ cd init.d

다음은 부팅하면서 실행할 명령들이 들어있는 bash 스크립트 파일을 만들어 주는 것이다. 여기서는 edison의 wifi 설정을 자동화하는 스크립트를 예로 해 보겠다. 텍스트에디터를 열어 wifi.sh 라는 이름으로 파일을 만들어 준다.

$ vi wifi.sh

파일에는 다음의 내용이 들어가야 한다.

#!/bin/sh

wpa_supplicant -B -Dnl80211 -iwlan0 -c/etc/wpa_supplicant/wpa_supplicant.conf
busybox udhcpc -i wlan0

내용을 저장하고 에디터를 종료했으면 chmod 명령으로 이 파일이 실행 가능하도록 해 줘야 한다.

$ chmod a+x wifi.sh

이 단계에서 스크립트가 정상 동작하는지 먼저 확인해 보는것이 좋다. 스크립트를 실행하고 출력이 아래와 같이 나오는지 확인한다. 

$ ./wifi.sh
Successfully initialized wpa_supplicant
udhcpc (v1.22.1) started
Sending discover...
Sending discover...
Sending discover...
Sending select for 192.168.0.34...
Lease of 192.168.0.34 obtained, lease time 86400
/etc/udhcpc.d/50default: Adding DNS 192.168.0.1
/etc/udhcpc.d/50default: Adding DNS 205.171.2.25

스크립트가 정상 실행되는걸 확인했으면, 실제로 google을 ping 해 동작을 확인해 본다. 

$ ping google.com
PING google.com (74.125.224.40): 56 bytes
64 bytes from 74.125.224.40: seq=0 ttl=57 time=43.711 ms
64 bytes from 74.125.224.40: seq=1 ttl=57 time=60.668 ms
^C
— google.com ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 43.711/52.189/60.668 ms

위와 같이 나오면 모든것이 정상 동작하는 것이다.

이제 이 스크립트가 linux가 부팅할 때 마다 매번 자동 실행되게 해 주기 위해 아래의 명령을 실행하고 아래와 같은 출력이 나오는걸 기다린다.

$ update-rc.d wifi.sh defaults
Adding system startup for /etc/init.d/wifi.sh

기본적으로 위의 명령은 스크립트에 대해 디폴트 rc.d 디렉토리 0~6에 심볼릭 링크를 만들어 준다. 생성된 디렉토리는 아래 명령으로 확인해 볼 수 있다.

$ ls -l /etc/rc?.d/*wifi*
lrwxrwxrwx    1 root    root     17 Sep 10 19:29  /etc/rc0.d/K20wifi.sh -> ../init.d/wifi.sh
lrwxrwxrwx    1 root    root     17 Sep 10 19:29  /etc/rc0.d/K20wifi.sh -> ../init.d/wifi.sh
lrwxrwxrwx    1 root    root     17 Sep 10 19:29  /etc/rc0.d/S20wifi.sh -> ../init.d/wifi.sh
lrwxrwxrwx    1 root    root     17 Sep 10 19:29  /etc/rc0.d/S20wifi.sh -> ../init.d/wifi.sh
lrwxrwxrwx    1 root    root     17 Sep 10 19:29  /etc/rc0.d/S20wifi.sh -> ../init.d/wifi.sh
lrwxrwxrwx    1 root    root     17 Sep 10 19:29  /etc/rc0.d/S20wifi.sh -> ../init.d/wifi.sh
lrwxrwxrwx    1 root    root     17 Sep 10 19:29  /etc/rc0.d/K20wifi.sh -> ../init.d/wifi.sh

디폴트로 0, 1, 6 디렉토리는 kill 동작을 위해 예약되어 있기 때문에 심볼릭 링크의 이름이 “K”로 시작한다. 이와 유사하게 2, 3, 4, 5 디렉토리는 start 동작을 위해 예약되어 있기 때문에 “S”로 시작한다. S 또는 K 뒤의 20이라는 숫자는 프로세스 hierachy를 정의한다. 20보다 작은 숫자를 가진 프로세스는 이 프로세스보다 먼저 시작되고 20보다 큰 숫자를 가진 프로세스는 이 프로세스 이후에 실행된다. 참고로 init.d 스크립트는 커널 부팅 과정중에 가장 마지막으로 실행된다. 부팅 순서에 관한 자세한 내용은 여기를 참고하면 된다.

모든것이 확인되었으면 시스템을 리부팅해서 정상동작 하는지 확인해본다.

$ reboot

Connection to 192.168.2.15 closed by remote host.

Connection to 192.168.2.15 closed.

잠시 기다린 후 다시 ssh로 연결한다.

$ ssh root@192.168.2.15

무선랜을 통해 ssh로 연결했으면 더 이상 확인할 필요 없이 정상동작 하는 것이고, 만일 dongle을 통해 ssh로 연결했으면 wpa_supplicant가 프로세스로 실행되고 있는지 확인해야 한다.


그리고 google.com으로 ping을 해 본다. 

$ ping google.com
PING google.com (74.125.224.40): 56 bytes
64 bytes from 74.125.224.40: seq=0 ttl=57 time=32.892 ms
64 bytes from 74.125.224.40: seq=1 ttl=57 time=47.575 ms
^C
— google.com ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 32.892/40.233/47.575 ms

여기까지 되었다면 모든것이 완료된 것이다.