라즈베리파이 갑자기 꺼짐 - lajeubelipai gabjagi kkeojim

제목대로 지난 달 초에 산 라즈베리파이2가 불안정해서 참 골치에요.

라즈비안에 별 거 안하고 pptpd랑 블루투스 서비스만 설치해서 작동 중인데

vpn 클라이언트는 항상 켜져 있기 때문에 연결이 끊어지지 않아야 하거든요.

오히려 서버가 멈추어 버리는 바람에 되던 연결이 끊어진 적이 오늘로 두 번째에요.

라즈비안에 저는 아무것도 안 했다 하나 원래 딸려오는 게 많아서 그런가?

가진 x86 보드랑 cpu 모아서 원격 데스크톱 게이트웨이를 하나 구성해야 하나 생각하면..

예전에 한 번 삽질하다 그만 둔 경험도 있고 지식도 형편없고

포럼에서 다른 운영체제를 구할까

자려고 누워서 횡설수설

이 게시물을...

라즈베리파이 안전 전원종료(Soft Shutdown)

황제곰2020. 9. 19. 0:23

안녕하세요. 이번 포스팅에서는 라즈베리파이의 안전 전원종료(Soft Shutdown) 방법에 대해서 알아보겠습니다.

라즈베리파이 갑자기 꺼짐 - lajeubelipai gabjagi kkeojim

일반적으로 대부분의 컴퓨터는 구입할 때 전원 종료를 위한 버튼이 있어서 버튼을 누르면 컴퓨터가 꺼지게 설계가 되어 있습니다.

라즈베리파이 갑자기 꺼짐 - lajeubelipai gabjagi kkeojim

라즈베리파이는 전원 인가를 위해서는 전원소켓에 파워서플라이나 충전기의 플러그를 꽂으면 되지만 전원 종료를 위한 버튼은 포함되어 있지 않습니다. 그 이유는 라즈베리파이재단에서 교육용 컴퓨터로 최대한 저렴한 가격에 라즈베리파이를 보급하기 위해서 꼭 필요한 기능만 넣었기 때문이라고 하네요(ㅠㅠ 그래도 엄청난 수량으로 만들기 때문에 단가가 몇 십원 밖에 안할 것 같은데 아쉽네요,,,,)

따로 전원 버튼이 없다보니 잘 모르는 경우에는 라즈베리파이의 전원 종료 방법을 몰라서 그냥 플러그를 뽑아서 전원을 끄게 되는데요.

라즈베리파이 갑자기 꺼짐 - lajeubelipai gabjagi kkeojim

갑자기 플러그를 뽑아서 전원을 종료시키면 안됩니다. 왜냐하면 라즈베리파이의 CPU가 SD카드에서 각종 데이터를 읽어나 쓰는 중에 갑자기 전원이 나가 버리면 SD카드에 불량 섹터가 생겨서 데이터가 손상되고 부트영역이 손상되면 부팅까지 안되는 경우가 생길수 있기 때문입니다. 저도 처음에는 몇번 플러그를 뽑아서 전원을 종료 했었는데 그 이후에 별 이상이 없었는데요. 어느날 갑자기 부팅이 안되서 확인하다보니 SD카드가 인식이 안되고 있다는 것을 알게 된 적이 있습니다.

따라서 안전하게 전원을 종료하기 위해서는 CPU 및 주변장치가 모든 활동을 종료시킬 수 있도록 해 주어야 하는데요. 이 때 사용할 수 있는 전원 종료 방법이 Soft Shutdown 이라고 부르는 명령어를 통한 방법입니다. 방법은 아주 간단한데요. 아래와 같은 명령어를 통해 라즈베리파이를 종료시키면 됩니다.(둘 중 어떤 명령어를 사용하셔도 괜찮습니다.)

sudo shutdown -h now sudo poweroff

위 명령어를 친 뒤 기다리면 라즈베리파이의 녹색 LED가(ACTLED) 깜박이다가 완전히 꺼지는데요. 그 때 전원 플러그를 빼면 안전하게 종료시킬 수 있습니다.

위와 같이 매번 명령어를 쳐서 종료하면 되긴 하지만 명령어를 쳐서 라즈베리파이를 종료하는 것이 번거로운 경우가 상당히 많습니다. 어떤 프로젝트를 위해서 라즈베리파이를 이미 케이스 내부에 고정시킨 경우나 인터넷 환경이 안되는 프로젝트를 진행중일 경우 키보드를 연결하거나 ssh로 접속해서 명령어를 치는 것은 여간 불편한 것이 아니겠죠?

라즈베리파이 갑자기 꺼짐 - lajeubelipai gabjagi kkeojim

이럴 때 라즈베리파이의 GPIO핀에 스위치를 연결해서 전원버튼으로 사용되도록 코드를 작성해 주면 안전 전원종료(Soft Shutdown)기능을 구현할 수 있습니다.

이번 포스팅에서는 브레드보드에 택트스위치를 연결해서 Soft Shutdown을 구현하는 방법에 대해서 살펴 보겠습니다.

회로 연결은 아래 사진과 같이 택트스위치의 양쪽 다리중 한쪽다리에 연결한 핀은 라즈베리파이의 GND핀에 다른 한쪽은 GPIO핀 중 하나에 연결해 주면 됩니다. 저는 물리적 핀번호 39(GND), 40번(GPIO21)을 사용했습니다.

라즈베리파이 갑자기 꺼짐 - lajeubelipai gabjagi kkeojim

회로 연결

참고로 라즈베리파이의 GPIO핀 배열은 아래 사진과 같습니다.

라즈베리파이 갑자기 꺼짐 - lajeubelipai gabjagi kkeojim

파이썬 gpiozero 라이브러리를 통한 soft shutdown

라즈베리파이에서 사용할 수 있는 파이썬 라이브러리 중 GpioZero 라이브러리를 사용하면 손쉽게 Soft Shutdown 기능을 구현할 수 있습니다. GpioZero 라이브러리에 대한 자세한 내용은 아래 포스팅을 참고해 주세요.

라이브러리 설치

라이브러리 설치에 앞서 아래 명령어를 통해 패키지 목록을 업데이트 및 최신화 해 줍니다.

sudo apt update sudo apt upgrade

이제 아래 명령어를 통해 파이썬3용 gpio-zero 라이브러리를 설치 해 줍니다.

pi@raspberrypi:~ $ sudo apt install python3-gpiozero

코드입력

아래와 같이 코드를 작성해 준뒤에 확장자 .py를 넣어서 저장해 줍니다.(저는 softshutdown.py 로 저장했습니다.)

#!/usr/bin/env python3 from gpiozero import Button # gpiozero 모듈에서 버튼 클래스 불러오기 import os # os 모듈 불러오기 Button(21).wait_for_press() # GPIO 21번에 버튼을 연결하고 눌릴때까지 기다리기 os.system("sudo shutdown -h now") # 버튼이 눌리면 soft shutdown 실행

이제 아래 명령어를 실행하고 버튼을 누르면 잠시뒤에 라즈베리파이가 안정적으로 종료되는 것을 확인 할 수 있습니다.

pi@raspberrypi:~/softshutdown $ python3 softshutdown.py &

위에서 앰퍼샌드(&기호)는 백그라운드에서 프로그램을 실행하라는 의미입니다.

코드입력(버튼 누른 뒤 일정 시간 이후 셧다운 실행)

위에서 작성한 코드도 동작이 잘 되긴하지만 실수로 버튼을 누를 경우에도 전원이 종료되는 단점이 있습니다. 이를 개선하기 위해 버튼이 최소한 몇초간 눌려야 전원이 종료되도록(Soft Shutdown) 코드를 수정해 보겠습니다. 아래와 같이 코드를 입력하고 .py의 확장자로 파일을 저장합니다.(저는 shutdown-hold.py로 저장했습니다.)

1 #!/usr/bin/env python3 2 from gpiozero import Button # 버튼클래스 3 from signal import pause # puase 함수 호출 4 import os, sys 5 6 offGPIO = int(sys.argv[1]) if len(sys.argv) >= 2 else 21 #gpio핀 넘버를 커맨트 명령어에서 지정, 입력을 안하면21번으로 설정 7 holdTime = int(sys.argv[2]) if len(sys.argv) >= 3 else 6 #버튼 홀드 시간을 커맨드 명령어로 지정, 입력을 안하면 6초 8 9 def shutdown(): #버튼이 눌리면 실행될 함수 10 os.system("sudo shutdown -h now") 11 12 btn = Button(offGPIO, hold_time=holdTime) #버튼 클래스 생성, 버튼이 눌린채로 유지될 시간도 지정 13 btn.when_held = shutdown #버튼이 지정된 시간만큼 눌릴뒤 떼어지면 shutdown 함수 실행 14 pause() #버튼 입력까지 대기

이제 아래 명령어를 통해 코드를 실행해 줍니다. 뒤에 추가한 21 3은 각각 GPIO21번 홀드시간 3초를 의미합니다.

pi@raspberrypi:~/softshutdown $ python3 shutdown-hold.py 21 3

이제 버튼을 3초가 누르고 있으면 soft shutdown 이 실행됩니다.

부팅시 soft shutdown 스크립트 자동 실행 설정하기

위에서 작성한 코드를 매번 새로 부팅할 때마다 실행해야 한다면 매우 번거롭겠죠? 부팅할 때마다 우리가 원하는 스크립트를 자동으로 실행되게 설정할 수 있는데요. 이 부분에 대해서는 아래 포스팅에 다양한 방법에 대해 설명해 두었으니 참고하시면 됩니다.

여러 방법 중 이번 포스팅에서는 가장 간편한 방법은 crontab을 사용한 방법을 통해 스크립트를 자동실행되도록 설정해 보겠습니다. crontab에 자동 실행될 스크립트를 지정하기 위해 아래 명령어를 입력해 줍니다.

pi@raspberrypi:~ $ sudo crontab -e

crontab이 뜨면 아래와 같이 자동실행하고자 하는 스크립트 소스를 절대경로로 추가해 줍니다.

라즈베리파이 갑자기 꺼짐 - lajeubelipai gabjagi kkeojim

@reboot python3 /home/pi/softshutdown/shutdown-hold.py &

@reboot는 매번 부팅될 때마다 해당 스크립트를 자동 실행하라는 의미입니다. 마지막에 붙인 &는 백그라운드에서 실행하라는 의미입니다

위에서 파이썬 언어를 사용한 방법은 사용자공간(userspace)을 통한 방법인데요. 라즈베리파이는 커널단에서도 soft shutdown 기능을 제공하고 있습니다. 커널을 통한 방법은 디바이스트리 오버레이에 gpio-shutdown또는 gpio-poweroff를 지정해 주면 됩니다.

gpio-shutdown 오버레이에 대해 알아 보기 위해 아래와 같이 디바이스트리 오버레이 이름과 -h 옵션을 함께 입력하면 해당 오버레이에 대한 설명이 나옵니다.

pi@raspberrypi:~/softshutdown $ dtoverlay -h gpio-shutdown Name: gpio-shutdown Info: Initiates a shutdown when GPIO pin changes. The given GPIO pin is configured as an input key that generates KEY_POWER events. This event is handled by systemd-logind by initiating a shutdown. Systemd versions older than 225 need an udev rule enable listening to the input device: ACTION!="REMOVE", SUBSYSTEM=="input", KERNEL=="event*", \ SUBSYSTEMS=="platform", DRIVERS=="gpio-keys", \ ATTRS{keys}=="116", TAG+="power-switch" Alternatively this event can be handled also on systems without systemd, just by traditional SysV init daemon. KEY_POWER event (keycode 116) needs to be mapped to KeyboardSignal on console and then kb::kbrequest inittab action which is triggered by KeyboardSignal from console can be configured to issue system shutdown. Steps for this configuration are: Add following lines to the /etc/console-setup/remap.inc file: # Key Power as special keypress keycode 116 = KeyboardSignal Then add following lines to /etc/inittab file: # Action on special keypress (Key Power) kb::kbrequest:/sbin/shutdown -t1 -a -h -P now And finally reload configuration by calling following commands: # dpkg-reconfigure console-setup # service console-setup reload # init q This overlay only handles shutdown. After shutdown, the system can be powered up again by driving GPIO3 low. The default configuration uses GPIO3 with a pullup, so if you connect a button between GPIO3 and GND (pin 5 and 6 on the 40-pin header), you get a shutdown and power-up button. Please note that Raspberry Pi 1 Model B rev 1 uses GPIO1 instead of GPIO3. Usage: dtoverlay=gpio-shutdown,<param>=<val> Params: gpio_pin GPIO pin to trigger on (default 3) For Raspberry Pi 1 Model B rev 1 set this explicitly to value 1, e.g.: dtoverlay=gpio-shutdown,gpio_pin=1 active_low When this is 1 (active low), a falling edge generates a key down event and a rising edge generates a key up event. When this is 0 (active high), this is reversed. The default is 1 (active low). gpio_pull Desired pull-up/down state (off, down, up) Default is "up". Note that the default pin (GPIO3) has an external pullup. Same applies for GPIO1 on Raspberry Pi 1 Model B rev 1. debounce Specify the debounce interval in milliseconds (default 100)

여러 옵션이 있는데 그중 gpio_pin 옵션은 어떤 핀에 버튼을 연결할지 지정하는 옵션입니다. 기본 옵션은 gpio3번(물리적핀 5번)입니다.

그럼 이제 이 디바이스트리오버레이를 활성화 하기 위해 /boot/config.txt 파일을 열어서 마지막 줄에 이 오버레이를 추가해 줍니다.

pi@raspberrypi:~/softshutdown $ sudo vim /boot/config.txt

라즈베리파이 갑자기 꺼짐 - lajeubelipai gabjagi kkeojim

저는 핀 gpio3번을 사용하기 위해 버튼을 gpio3번에 연결했기 때문에 gpio_pin 옵션은 지정하지 않았는데 다른 핀을 사용하려면 지정해 줘야 삽니다. 그리고 지연시간을 2초를 주기 위해 위와 같이 debounce옵션에 2000을 입력했습니다. 파일을 저장한 뒤에 아래 명령어를 통해 라즈베리파이를 재 부팅해 줍니다.

pi@raspberrypi:~/softshutdown $ sudo reboot

그럼 디바이스트리오버레이가 활성화 되어서 이제 gpio3번에 연결된 택트스위치를 2초이상 누르면 soft shutdown이 활성화 되어 안정적으로 전원 종료가 가능합니다.

이 방법은 좋은 점이 하나 더 있는데요. gpio3번에 택트 스위치를 연결하면 soft shutdown 기능을 통해 라즈베리파이를 종료 하는 것 뿐 아니라 softshutdown 이 완료된 이후에 전원플러그를 뺐다가 연결하지 않고 스위치를 누르면 다시 부팅을 시킬 수 있다는 점입니다.

아래 영상에서 보시는 바와 같이 전원 종료 뿐 아니라 부팅도 가능하다는 것을 확인 할 수 있습니다.

라즈베리파이 갑자기 꺼짐 - lajeubelipai gabjagi kkeojim

* 참고로 다시 부팅시키는 기능은 스위치를 gpio3번 으로 지정했을때만 가능하고 그밖의 핀을 사용할 때는 이 기능은 사용이 안됩니다.( gpio3번은 I2C 통신에 사용되는 핀이기 때문에 I2C 통신이 필요하면 다른 핀을 사용하셔야 합니다.)

그럼 이만~^^