- 출처 : 유닉스 리눅스 쉘스크립트 예제사전_한빛미디어
명령어: who, ps, shutdown
키워드: 로그인 사용자, 셧다운, 프로세스, 확인, 정지
사용처: 셧다운 절차를 스크립트로 작성해서 확인 항목을 자동으로 체크하고 전원을 내리고 싶을 때
실행 예제
# ./shutdown.sh
[ERROR] who 명령어 출력이 2줄 이상: 작업 중인 사용자가 있습니다.
# ./shutdown.sh
Broadcast message from user1@linux
(/dev/pts/1) at 15:32 ...
The system is going down for halt NOW!
스크립트
#!/bin/bash
# 자기 이외의 사용자가 로그인하지 않았는지 who 명령어 출력으로 확인
other_user=$(who | wc -l)
if [ "$other_user" -ge 2 ]; then # if문 -------------------------------- 1
echo "[ERROR] who 명령어 출력이 2줄 이상 : 작업 중인 사용자가 있습니다." >&2
exit 1
fi
# 미리 정지해야 할 프로세스가 아직 남아 있는지 확인
commname="/usr/libexec/mysqld"
ps ax -o command | grep -q "^$commname"
if [ $? -eq 0 ]; then # if문 ------------------------------------------- 2
echo "[ERROR] 셧다운 중지 : 프로세스 $commname 실행 중" >&2
exit 2
fi
# 셧다운 실행. Mac/FreeBSD는 주의사항 참조
shutdown -h now # ----------------------------------------------------- 3
해설
이 스크립트는 머신을 셧다운합니다. 셧다운 전에 두 가지를 확인합니다. 다음은 서버운용 시에도 자주 확인하는 부분입니다.
- 다른 사용자가 로그인하지 않았는가?
- 미리 멈춰야 할 프로세스가 실행되어 있지 않은가?
머신 셧다운은 중요 작업으로 작업 절차가 정해져 있는 경우가 많습니다. 하지만 그런 작업서만으로는 아직 익숙하지 않은 사용자가 혼란을 일으켜 실수를 할지도 모릅니다.
예를 들어 ‘셧다운 전에 다른 사용자가 로그인했는지 확인할 것’이라고 작업서에 적혀 있어도 실제로 어떤 명령어로 확인해야 하는지 모르거나 명령어는 실행했지만 출력 결과를 오인할 수도 있습니다. 따라서 예제처럼 스크립트를 작성한 뒤 ‘스크립트 shutdown.sh로 셧다운할 것’이라고 정해두면 그럴 일이 없습니다.
1에서 who 명령어출력 결과를 이용해서 현재 로그인 사용자를 확인합니다. who 명령어 출력은 OS에 따라 조금씩 다르지만 다음처럼 현재 로그인 중인 사용자 목록을 표시합니다. 첫 번째 컬럼이 사용자명, 두 번째 컬럼이 이용하고 있는 제어 터미널, 세 번째 컬럼이 로그인 시각입니다.
- 현재 로그인한 사용자 표시
$ who user1 tty1 2014-02-01 11:36 ogong pts/0 2014-01-29 22:36 (10.211.55.2) ogong pts/1 2014-02-01 11:26 (10.211.55.2)
여기서 user1이라는 사용자가 셧다운 조작을 한다고 가정합니다. ogong이라는 사용자가 외부에서 로그인해서 어떤 작업을 하고 있으므로 어떤 알림 없이 그냥 셧다운하면 작업 중인 데이터에 큰 영향이 갈지도 모릅니다.
1에서 who 명령어 출력이 두 줄 이상이면 다른 사용자가 있다고 판별하는 방법으로 다른 사용자가 로그인 중인지 확인합니다. who 명령어 출력을 wc 명령행 수만 출력하는 -l 옵션에 파이프로 이어서 줄 수를 카운트합니다. 여기서 who 명령행 수 즉 현재 로그인 사용자 수를 test 명령어 연산자 -ge (Greater Than)로 비교합니다. 여기서 test 명령어 대소 비교 연산자는 ShellScript 연산자 를 참조하기 바랍니다. 만약 2줄 이상이면 다른 사용자가 로그인 중이라고 보고 에러를 표시하고 종료합니다.
1의 test 명령어 대소 비교 시 리눅스나 FreeBSD의 GUI 환경, Mac을 사용할 때 주의해야 합니다. 일반적으로 유닉스 환경에서 X Window System 등의 GUI를 사용하면 GUI 화면에 로그인한 사용자와 거기서 터미널을 사용하는 사용자가 있는 것이 보통이므로 3줄 이상부터 다른 사용자가 있다고 보는 것이 적절합니다. 따라서 1은 GUI환경에서 다음처럼 지정합니다.
if [ "$other_user" -ge 3 ]; then
이어서 2 는 셧다운 전에 프로세스를 확인합니다. 여기서 ‘셧다운 전에 MySQL을 수동으로 정지할 것’이라는 절차가 있다고 가정합니다. 이 시스템의 MySQL을 실행하는 명령어 /usr/libexec/mysqld 프로세스가 존재하는지 ps 명령어와 grep 명령어로 확인합니다. 프로세스가 존재하면 grep 명령어는 종료 스테이터스로 0을 돌려주므로 이걸 if문으로 비교해서 에러를 표시합니다.
여기까지 확인이 끝나면 3 에서 shutdown 명령어를 실행합니다. 여기서 -h 옵션은 halt(정지)를 의미하는 옵션으로 시스템을 정지합니다. shutdown 명령어는 재실행을 의미하는 -r(reboot) 옵션도 자주 사용합니다.
shutdown 명령어는 인수로 TIME(시간)을 지정해서 그만큼 시간이 지난 다음 시스템을 종료합니다. TIME은 대부분 now(당장)를 지정하는 일이 많습니다. 3 에서도 now를 지정해서 시스템을 종료합니다.
주의사항
- 이 스크립트는 shutdown 명령어를 실행하기 위해 root권한으로 실행해야 합니다. 구체적으로는 root 사용자로 실행하거나 Mac이나 우분투라면 sudo 명령어를 이용하기 바랍니다.
- shutdown 명령어를 실행할 때 OS마다 지정 방법이 조금씩 다릅니다. FreeBSD는 shutdown 명령어로 전원을 내릴 때 -h 옵션이 아니라 -p 옵션을 이요합니다. 따라서 3 을 다음처럼 수정해야 합니다.
shutdown -p now