Commit 530e85ef by hellrazah

- "system 입문" 문서 추가

parent 068771fc
Showing with 354 additions and 5 deletions
### OSS (Open Source Software) ### OSS (Open Source Software) 관련 문서
#### 백서(whitepaper) 기반 세미나 (seminar) #### 백서(whitepaper) 기반 세미나 (seminar)
* 일시 : 매월 째주 수요일 16시 ~ 18시 * 일시 : 매월 째주 수요일 16시 ~ 18시
* 장소 : plug34 회의실 (강남구 역삼동 839-5번지 2층) * 장소 : plug34 회의실 (강남구 역삼동 839-5번지 2층)
* 문의 : support@iorchard.net, 02-824-2544
--- ---
문의 : support@iorchard.net, 02-824-2544 문의 : support@iorchard.net, 02-824-2544
\ No newline at end of file
# systemd 입문
# systemd 입문
## 개요
현재 대부분의 대표적인 linux 배포판에 systemd가 기본 init system으로 채택되었다.
fedora를 시작으로 rhel(centos), debian, ubuntu, opensuse, archlinux, coreos 등등 모두 이제 pid 1는 systemd이다.
좋든 싫든 이제 사실상 표준이다. linux를 사용하기위해선 알아야한다.
이 문서는 systemd에서 자주 사용될만한 부분만 간단히 기술하였다. 자세한 내용이 필요하다면 manpage와
https://www.freedesktop.org/wiki/Software/systemd/를 참고하도록 하자.
## 논란
사실 systemd로 채택되면서 많은 논란이 있었다.
가장 논란은 systemd가 혼자 너무 역할을 한다는데 있다. linux(unix) 기본 철학인 '하나의 프로그램은 하나의 일'만 처리하지 않고, 모두 통합하였다.
예전 linux를 공부할때 `seq`를 이상하게 생각했었다. `seq`는 순차적으로 숫자를 출력하는프로그램이다. `seq 1 10`하면 1부터 10이 순서대로 출력된다. 그뿐이다.
'이게 뭔 대단한 프로그램이라고 모든 리눅스 배포판에 포함되었는가?' 나중에 알게된 이유는 shell script에서 찾을수 있었다.
```sh
for num in `seq 1 10`; do
echo $num
done
```
systemd는 init, pam, rsyslog, udev, cron, at, cgroups, date, locale, hostname 등등을 모두 통합하였다. ([A monster named systemd](https://www.youtube.com/watch?v=bdmv2FQRHWg) 링크 참고)
이러한 통합이 누군가에게 장점이 될수고 있겠으나, 나를 포함한 기존 사용자에게 혼란을 가져다 주었다. upstart때만 하더라도 daemon 관리정도의 문서만 찾아보았는데, systemd는 다르다.
그리고 또 눈에 많이 띄이는 것은 systemd의 핵심 독일 개발자 Lennart Poettering에 대한 얘기이다. pulseaudio 개발자이기도 한데, 커뮤니티와 의사소통 문제(독재적인 성향)으로 문제가 많은듯했다. (https://en.wikipedia.org/wiki/Lennart_Poettering)
## system 확인
pid 1을 확인하였다.
```sh
root 1 0 0 Feb10 ? 00:00:02 /lib/systemd/systemd
```
debian wheezy에서도 systemd를 설치(`apt-get install systemd`)할수 있는데 pid 1이 익숙한 /sbin/init이었다. 확인해보니, systemd로 symlink걸려있었다.
## 종료, 리부팅
systemd에서는 `systemctl`로 system과 service를 관리한다. 시스템을 관련 명령들은 아래와 같다.
* 종료 : `systemctl halt`, `systemctl poweroff`
* 리부팅 : `systemctl reboot`
그럼 기존의 `halt`, `shutdown`, `reboot`, `poweroff`는 없어졌나?
```sh
# ls -al /sbin | grep systemctl
lrwxrwxrwx 1 root root 14 Nov 22 04:00 halt -> /bin/systemctl
lrwxrwxrwx 1 root root 14 Nov 22 04:00 poweroff -> /bin/systemctl
lrwxrwxrwx 1 root root 14 Nov 22 04:00 reboot -> /bin/systemctl
lrwxrwxrwx 1 root root 14 Nov 22 04:00 shutdown -> /bin/systemctl
lrwxrwxrwx 1 root root 14 Nov 22 04:00 runlevel -> /bin/systemctl
lrwxrwxrwx 1 root root 14 Nov 22 04:00 telinit -> /bin/systemctl
```
모두 systemctl로 symlink 걸려있었다. 그런데 reboot, halt 등등 모두 systemctl로 걸려있다. 이럼 어떻게 처리되나?
소스(https://github.com/systemd/systemd/blob/master/src/systemctl/systemctl.c#L5552) 를 보니 shell의 첫번째 인자값(argv[0])으로 처리하고 있었다.
```c
streq(argv[0], "halt") ? "Halt" :
streq(argv[0], "poweroff") ? "PowerOff" :
streq(argv[0], "reboot") ? "Reboot" :
```
이처럼 예전 사용자를 위한 legacy한 방법은 기본으로 제공되었다.
## 부팅 시간 확인
systemd-analyze로 boot-up에 걸린 시간을 확인할수 있다.
```sh
# systemd-analyze time
Startup finished in 758ms (kernel) + 1.039s (userspace) = 1.797s
```
각 unit에 대한 시간을 확인할수도 있다.
```sh
# systemd-analyze blame
202ms console-setup.service
190ms keyboard-setup.service
100ms exim4.service
77ms systemd-fsck-root.service
76ms networking.service
59ms kbd.service
52ms systemd-udev-trigger.service
36ms systemd-tmpfiles-setup-dev.service
33ms rc-local.service
30ms systemd-modules-load.service
26ms nginx.service
24ms dev-hugepages.mount
22ms sys-kernel-debug.mount
21ms dev-mqueue.mount
19ms systemd-tmpfiles-setup.service
18ms systemd-tmpfiles-clean.service
16ms dev-disk-by\x2duuid-9ec04e4a\x2dbefa\x2d4dec\x2da8e6\x2d40e4ee0636eb.swap
15ms kmod-static-nodes.service
14ms rsyslog.service
13ms systemd-udevd.service
12ms systemd-random-seed.service
12ms systemd-user-sessions.service
12ms systemd-logind.service
10ms systemd-sysctl.service
10ms systemd-update-utmp.service
10ms udev-finish.service
8ms systemd-journal-flush.service
5ms systemd-remount-fs.service
4ms systemd-update-utmp-runlevel.service
```
## service 기본 관리
systemd에서는 관리의 단위로 'unit'을 사용한다. 이 unit은 여러 종류가 있는데 (service, target, swap, device등) 데몬관리에서는 'service'라는 unit으로 관리하게 된다.
unit은 `nginx.service` 와 같이 확장자처럼 unit 타입에 대한 suffix가 붙는다. 이 unit으로 처리하면 된다.
nginx를 시작할 경우라면 아래와 같다.
```sh
# sudo systemctl start nginx.service
```
종료와 재시작도 마찬가지다.
```sh
# sudo systemctl stop nginx.service
# sudo systemctl restart nginx.service
```
service가 구동중인지는 is-active로 확인할수도 있다.
```sh
# sudo systemctl is-active nginx.service
```
'active', 'inactive' 상태로 나타나며 running중이라면 exit code로 0을 리턴한다.
update-rc.d와 같이 부팅시 자동시작하게하려면 enable과 disable을 사용하면 된다.
```sh
# sudo systemctl enable nginx.service
# sudo systemctl disable nginx.service
```
그리고 enable되어 있는지 disable되어 있는지는 아래와 같이 확인할수도 있다.
```sh
# sudo systemctl is-enabled nginx.service
enabled
```
service에 대한 상태를 확인할수도 있다.
```sh
# systemctl status nginx
● nginx.service - A high performance web server and a reverse proxy server
Loaded: loaded (/lib/systemd/system/nginx.service; enabled)
Active: active (running) since Thu 2016-02-11 06:54:53 KST; 4min 5s ago
Main PID: 30540 (nginx)
CGroup: /system.slice/nginx.service
├─30540 nginx: master process /usr/sbin/nginx -g daemon on; master_process on;
├─30541 nginx: worker process
├─30542 nginx: worker process
├─30543 nginx: worker process
└─30544 nginx: worker process
```
시스템의 현재 구동된 service들(혹은 구동되야할)을 볼수도 있다.
```sh
# systemctl list-units --type=service
UNIT LOAD ACTIVE SUB DESCRIPTION
acpid.service loaded active running ACPI event daemon
console-setup.service loaded active exited LSB: Set console font and keymap
cron.service loaded active running Regular background program processing daemon
dbus.service loaded active running D-Bus System Message Bus
exim4.service loaded active running LSB: exim Mail Transport Agent
getty@tty1.service loaded active running Getty on tty1
ifup@eth0.service loaded active exited ifup for eth0
kbd.service loaded active exited LSB: Prepare console
keyboard-setup.service loaded active exited LSB: Set preliminary keymap
kmod-static-nodes.service loaded active exited Create list of required static device nodes for the current
networking.service loaded active exited LSB: Raise network interfaces.
nginx.service loaded active running A high performance web server and a reverse proxy server
rc-local.service loaded active exited /etc/rc.local Compatibility
rsyslog.service loaded active running System Logging Service
ssh.service loaded active running OpenBSD Secure Shell server
systemd-fsck-root.service loaded active exited File System Check on Root Device
systemd-journald.service loaded active running Journal Service
systemd-logind.service loaded active running Login Service
systemd-modules-load.service loaded active exited Load Kernel Modules
systemd-random-seed.service loaded active exited Load/Save Random Seed
systemd-remount-fs.service loaded active exited Remount Root and Kernel File Systems
systemd-sysctl.service loaded active exited Apply Kernel Variables
systemd-tmpfiles-setup-dev.service loaded active exited Create Static Device Nodes in /dev
systemd-tmpfiles-setup.service loaded active exited Create Volatile Files and Directories
systemd-udev-trigger.service loaded active exited udev Coldplug all Devices
systemd-udevd.service loaded active running udev Kernel Device Manager
systemd-update-utmp.service loaded active exited Update UTMP about System Boot/Shutdown
systemd-user-sessions.service loaded active exited Permit User Sessions
udev-finish.service loaded active exited Copy rules generated while the root was ro
```
만약 정의된 모든 service unit을 확인하려면 아래와 같다.
```
# systemctl list-unit-files --type=service
```
## service 파일
예전 sysVinit의 경우 LSB(linux standard base) init script (/etc/init.d)로 관리했었다.
start, stop, restart, status등 command를 모두 script로 작성했었지만, systemd는 unit file만 작성하면 된다.
unit files들은 보통 /etc/systemd/system (local configuration)혹은 /lib/systemd/system (installed package)에 위치한다.
아래는 nginx의 unit file이다. (/lib/systemd/system/nginx.service)
```
[Unit]
Description=A high performance web server and a reverse proxy server
After=network.target
[Service]
Type=forking
PIDFile=/run/nginx.pid
ExecStartPre=/usr/sbin/nginx -t -q -g 'daemon on; master_process on;'
ExecStart=/usr/sbin/nginx -g 'daemon on; master_process on;'
ExecReload=/usr/sbin/nginx -g 'daemon on; master_process on;' -s reload
ExecStop=-/sbin/start-stop-daemon --quiet --stop --retry QUIT/5 --pidfile /run/nginx.pid
TimeoutStopSec=5
KillMode=mixed
[Install]
WantedBy=multi-user.target
```
위를 간단히 해석하자면 아래와 같다.
* Unit section의 `After` : 기존 sysVinit의 경우 /etc/rc?.d를 순차적으로 실행했으나 systemd는 모든 unit을 동시에 병렬적으로 실행한다.
이때 전후 의존 관계가 있는 경우라면 설정해줄수 있다. 위의 경우 network.target이 실행된 후에, 즉 네트워크가 구동된 뒤에 수행되도록 한다. 비슷한 `Requires`가 있는데 이는 해당 서비스가 실패한다면 실행하지 않지만, `After`는 실패유무와 무관하게 실행된다.
target은 unit들의 group이다.
* Service section : 서비스 실행에 필요한 값들을 설정했다.
* Install section의 `WantedBy` : `systemctl enable`로 unit을 등록할때 위치이다. nginx를 enable로 등록하게 되면 /etc/systemd/system/multi-user.target.wants라는 디렉토리에 unit 파일이 symlink걸린다.
unit 파일 자세한 설정은 아래링크에서 확인하도록 하자.
https://www.freedesktop.org/software/systemd/man/systemd.unit.html
## runlevel
기존의 runlevel은 0~6까지 사실상 의미없는 숫자로 부여되었다. systemd도 legacy로 runlevel의 개념을 남겨두고 있지만, 직접적으로 사용하진 않는다.
```sh
# ls -al /lib/systemd/system/runlevel*
lrwxrwxrwx 1 root root 15 Nov 22 04:00 /lib/systemd/system/runlevel0.target -> poweroff.target
lrwxrwxrwx 1 root root 13 Nov 22 04:00 /lib/systemd/system/runlevel1.target -> rescue.target
lrwxrwxrwx 1 root root 17 Nov 22 04:00 /lib/systemd/system/runlevel2.target -> multi-user.target
lrwxrwxrwx 1 root root 17 Nov 22 04:00 /lib/systemd/system/runlevel3.target -> multi-user.target
lrwxrwxrwx 1 root root 17 Nov 22 04:00 /lib/systemd/system/runlevel4.target -> multi-user.target
lrwxrwxrwx 1 root root 16 Nov 22 04:00 /lib/systemd/system/runlevel5.target -> graphical.target
lrwxrwxrwx 1 root root 13 Nov 22 04:00 /lib/systemd/system/runlevel6.target -> reboot.target
```
기본 target 은 아래와 같이 확인/설정할수 있다.
```sh
# systemctl get-default
multi-user.target
# systemctl set-default graphic.target
```
## rc.local
debian jessie의 경우 rc.local 파일이 존재했다. service로 이미 등록되어 있어 /etc/rc.local을 실행하게 되어 있었으나, archlinux의 경우 /etc/rc.local이 없었다.
이럴경우 아래와 같이 등록하면 된다. /lib/systemd/system/rc-local.service 파일을 생성한다.
```
[Unit]
Description=/etc/rc.local compatibility
[Service]
Type=oneshot
ExecStart=/etc/rc.local
[Install]
WantedBy=multi-user.target
```
이제 /etc/rc.local 파일을 생성한뒤 `chmod +x /etc/rc.local`로 실행 권한을 준다. 그리고 `systemctl enable rc-local`로 startup시 시작하도록 등록하면 된다.
## hostname 설정
```sh
# hostnamectl
Static hostname: jessie
Icon name: computer-vm
Chassis: vm
Machine ID: 3e14b64449e34e03b36291a23dca905d
Boot ID: 4de0904ed72b41d08e36e7c5c39b318e
Virtualization: kvm
Operating System: Debian GNU/Linux 8 (jessie)
Kernel: Linux 3.16.0-4-amd64
Architecture: x86-64
# hostnamectl set-hostname newhostname
```
## 시간 설정
```sh
# timedatectl
Local time: Thu 2016-02-11 08:35:50 KST
Universal time: Wed 2016-02-10 23:35:50 UTC
RTC time: Wed 2016-02-10 23:35:50
Time zone: Asia/Seoul (KST, +0900)
NTP enabled: no
NTP synchronized: no
RTC in local TZ: no
DST active: n/a
# timedatectl set-timezone Asia/Tokyo
```
## log 관리
systemd는 `journalctl`로 log도 관리한다. journald라는 daemon이 돌면서 log를 수집하고 `journalctl`로 control한다.
journald는 /etc/systemd/journald.conf에서 설정(Compress, Maxsize, Level등)하며 log를 /run/log/journal 밑에 binary로 저장한다.
보통 rsyslog와 journald가 동시에 구동되는데 아직 rsyslog의 의존성 걸린 package들이 많아 rsyslog를 완전히 대체하진 못해보인다.
rhel의 경우 rsyslog가 imjournal이라는 input module을 사용하여 journald의 binary log를 access한다.
journalctl은 기본적으로 output을 less로 pipe하여 pager로 사용한다. `--no-pager`로 pager없이도 가능하다. $SYSTEMD_PAGER를 변경할수 있다.
```sh
# journalctl
-- Logs begin at Wed 2016-02-10 23:41:22 KST, end at Thu 2016-02-11 09:17:01 KST. --
Feb 10 23:41:22 jessie systemd-journal[115]: Runtime journal is using 4.0M (max allowed 9.4M, trying to leave 14.1M f
Feb 10 23:41:22 jessie systemd-journal[115]: Runtime journal is using 4.0M (max allowed 9.4M, trying to leave 14.1M f
Feb 10 23:41:22 jessie kernel: Initializing cgroup subsys cpuset
Feb 10 23:41:22 jessie kernel: Initializing cgroup subsys cpu
Feb 10 23:41:22 jessie kernel: Initializing cgroup subsys cpuacct
```
다양한 filtering option들이 있다.
```sh
# journalctl --since "2015-01-10" --until "2015-01-11 03:00"
# journalctl --since yesterday
# journalctl -u nginx.service # unit
# journalctl -p crit # priority
```
tail -f와 같은 옵션으로 `-f`를 지원하며, `-k` 혹은 `--dmesg`로 kernel message를 볼수 있고, `-o json` 옵션으로 output을 json으로 뽑을수도 있다.
http://0pointer.de/blog/projects/the-biggest-myths
http://0pointer.de/blog/projects/systemd.html
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment