2013. 12. 26. 11:25

[Linux/Ubuntu process 관리] process(프로세스) 관련 명령들 (ps, pgrep, fuser, nice, fg, bg, jobs, disown, kill, killall, nohup, at, batch, atq, atrm, crontab)

pgrep으로 process 검색하기


다음과 같이 'gnome' 문자열을 포함하는 프로세스의 PID를 나열한다.

~$ pgrep gnome

1809

1828

1879

1911

1918

1923

2089

3857

3860

~$


-l 옵션을 사용하여 명령을 구한다.

~$ pgrep -l gnome

1809 gnome-keyring-d

1828 gnome-session

1879 gnome-settings-

1911 gnome-panel

1918 polkit-gnome-au

1923 gnome-power-man

2089 gnome-screensav

3919 gnome-terminal

3922 gnome-pty-helpe

~$


특정 user의 프로세스를 구한다.

~$ pgrep -lu greenfish

1809 gnome-keyring-d

1828 gnome-session

1861 ssh-agent

...

4045 gnome-terminal

4048 gnome-pty-helpe

4049 bash

~$


gedit 프로세스를 구한다.

~$ ps -p `pgrep gedit`

  PID TTY          TIME CMD

 4286 ?        00:00:00 gedit

~$


gedit 프로세스를 구한다(full 정보).

~$ ps -fp $(pgrep gedit)

UID        PID  PPID  C STIME TTY          TIME CMD

1000      4286     1  0 14:04 ?        00:00:00 gedit

~$


gnome을 포함하는 여러개의 프로세스를 구한다. `pgrep gnome`은 1809 ... 와 같은 효과를 준다.

$(pgrep gnome)도 마찬가지이다.

~$ ps -p `pgrep gnome`

  PID TTY      STAT   TIME COMMAND

 1809 ?        Sl     0:00 /usr/bin/gnome-keyring-daemon --daemonize --login

 1828 ?        Ssl    0:00 gnome-session --session=ubuntu

 1879 ?        Ssl    0:01 /usr/lib/gnome-settings-daemon/gnome-settings-daemon

 1911 ?        Sl     0:01 gnome-panel

 1918 ?        Sl     0:00 /usr/lib/policykit-1-gnome/polkit-gnome-authenticatio

 1923 ?        Sl     0:00 gnome-power-manager

 2089 ?        Ss     0:00 gnome-screensaver

 4445 ?        Sl     0:00 gnome-terminal

 4448 ?        S      0:00 gnome-pty-helper

~$ ps -p 1809 1828 1879 1911 1918 1923 2089 4445 4448

  PID TTY      STAT   TIME COMMAND

 1809 ?        Sl     0:00 /usr/bin/gnome-keyring-daemon --daemonize --login

 1828 ?        Ssl    0:00 gnome-session --session=ubuntu

 1879 ?        Ssl    0:01 /usr/lib/gnome-settings-daemon/gnome-settings-daemon

 1911 ?        Sl     0:01 gnome-panel

 1918 ?        Sl     0:00 /usr/lib/policykit-1-gnome/polkit-gnome-authenticatio

 1923 ?        Sl     0:00 gnome-power-manager

 2089 ?        Ss     0:00 gnome-screensaver

 4445 ?        Sl     0:01 gnome-terminal

 4448 ?        S      0:00 gnome-pty-helper

~$


gedit를 찾아 우선순위를 향상시킨다.

~$ sudo renice -5 $(pgrep gedit)

4286: old priority 0, new priority -5

~$


fuser를 사용하여 프로세스 검색하기


우선, 

[Research/Ubuntu] - [Linux/Ubuntu 파일 시스템 관리] file system mount, un-mount(마운트, umount) 하기

에 있는 file_lock.c를 다음과 같이 빌드한다.(해당 post에 있는 lsof 명령과 fuser는 밀접한 관계가 있다)

~$ gedit file_lock.c

~$ cc -o file_lock file_lock.c

file_lock.c: In function ‘main’:

file_lock.c:16:7: warning: incompatible implicit declaration of built-in function ‘exit’

~$


다음과 같이 lock_me.dmy 파일을 생성한다.

~$ echo "01234567890" >> lock_me.dmy

~$


다음과 같이 file_lock을 실행하고, CTRL+Z를 누른다. 그리고, -auv 옵션을 이용하여 lock_me.dmy 파일을 열고 있는 프로세스를 나열한다.

~$ ./file_lock lock_me.dmy 

Return value of fcntl:0

[0000](11) 0123456789

[0001](11) 0123456789

^Z

[1]+  Stopped                 ./file_lock lock_me.dmy

~$ ./file_lock lock_me.dmy 

Return value of fcntl:0

[0000](11) 0123456789

[0001](11) 0123456789

[0002](11) 0123456789

^Z

[2]+  Stopped                 ./file_lock lock_me.dmy

~$ fuser -auv lock_me.dmy

                     USER        PID ACCESS COMMAND

lock_me.dmy:         greenfish   4100 F.... (greenfish)file_lock

                     greenfish   4101 F.... (greenfish)file_lock

~$

-a는 모든 프로세스를, -u는 프로세스의 owner를, -v는 자세한 정보를 출력해주는 옵션이다.


아래와 같이 -m 옵션을 이용하면, lock_me.dmy가 mount되어 있는 file system에서 실행되고 있는 프로세스를 나열한다.

~$ fuser -mauv lock_me.dmy

                     USER        PID ACCESS COMMAND

lock_me.dmy:         root     kernel mount (root)/

                     greenfish   1809 Frce. (greenfish)gnome-keyring-d

                     greenfish   1828 Frce. (greenfish)gnome-session

...

                     greenfish   4100 Frce. (greenfish)file_lock

                     greenfish   4101 Frce. (greenfish)file_lock

                     greenfish   4106 .rce. (greenfish)bash

~$

위 열거된 프로세스의 command는 모두 lock_me.dmy가 mount된 file system에 있는 파일이다.


아래와 같이 lock_me.dmy를 열고 있는 프로세스를 강제 종료한다.(SIGKILL)

~$ fuser -k lock_me.dmy

lock_me.dmy:          4100  4101

[1]-  Killed                  ./file_lock lock_me.dmy

[2]+  Killed                  ./file_lock lock_me.dmy

~$


그러면 아래와 같이 이제 실행되는 프로세스가 없다.

~$ fuser -auv lock_me.dmy

                     USER        PID ACCESS COMMAND

lock_me.dmy:

~$


fuser에서 지원되는 signal를 나열한다.

~$ fuser -l

HUP INT QUIT ILL TRAP ABRT IOT BUS FPE KILL USR1 SEGV USR2 PIPE ALRM TERM

STKFLT CHLD CONT STOP TSTP TTIN TTOU URG XCPU XFSZ VTALRM PROF WINCH IO PWR SYS

UNUSED

~$


다음과 같이 gedit에 HUP signal을 보낸다.

~$ sudo fuser -k -HUP /usr/bin/gedit

/usr/bin/gedit:       4186e

~$


실행중인 process 변경하기


실행중인 process의 행동을 변경할 수 있다. renice 명령으로 실행중인 process에 대한 시스템의 scheduler의 priority를 조절할 수 있다. nice 명령으로 default priority를 결정하고 process 실행시의 priority를 높이거나 낮출 수 있다. (주의: nice를 통해 높은 우선순위(음수)를 지정하는 경우 시스템의 crash를 유발할 수 있음)


현재의 nice 값은 다음과 같이 확인한다.

~$ nice

0

~$


다음과 같이 ls 명령의 nice를 변경하여 실행할 수 있다.

높은 우선순위인 경우, root 권한이 필요하다.

~$ nice -n 10 ls

backup_000  Documents  examples.desktop  mybackup  poem    temp       Videos

Desktop     Downloads  Music Pictures  Public  Templates

~$ nice -n -10 ls

nice: cannot set niceness: Permission denied

backup_000  Documents  examples.desktop  mybackup  poem    temp       Videos

Desktop     Downloads  Music Pictures  Public  Templates

~$ sudo nice -n -10 ls

backup_000  Documents  examples.desktop  mybackup  poem    temp       Videos

Desktop     Downloads  Music Pictures  Public  Templates

~$


아래와 같이 특정 사용자 권한으로 실행되는 process의 nice를 일괄 수정할 수 있다.

~$ ps -u greenfish -o pid,comm,nice

  PID COMMAND          NI

 1809 gnome-keyring-d   0

 1828 gnome-session     0

 1861 ssh-agent         0

...

 3561 bash              0

 3625 bash              0

 3680 ps                0

~$ renice +2 -u greenfish

1000: old priority 0, new priority 2

~$ ps -u greenfish -o pid,comm,nice

  PID COMMAND          NI

 1809 gnome-keyring-d   2

 1828 gnome-session     2

 1861 ssh-agent         2

 3561 bash              2

 3625 bash              2

 3682 ps                2

~$


다음과 같이 특정 process의 nice를 수정할 수 있다.

~$ ps -p 3561 -o pid,comm,nice

  PID COMMAND          NI

 3561 bash              2

~$ renice +3 3561

3561: old priority 2, new priority 3

~$ ps -p 3561 -o pid,comm,nice

  PID COMMAND          NI

 3561 bash              3

~$


아래와 같이 특정 사용자에서 조건에 맞는 process의 nice를 조절할 수 있다.

~$ sudo renice -3 `pgrep -u greenfish bash`

3561: old priority 3, new priority -3

3625: old priority 2, new priority -3

~$


실행중인 process 변경하기


shell에서 실행된 명령은 기본적으로 foreground에서 실행된다. 이는, 해당 명령이 종료될 때 까지 다른 명령을 실행, 즉, 입력할 수 없다는 뜻이다. 명령에 &를 추가하면, background로 실행할 수 있다. fg, bg, 그리고 jobs 명령으로 background와 foreground간의 전환이 가능하다.


우선 다음과 같이 gedit를 실행한다. 우선, bg를 실행했을때 현재 background 작업이 없음이 확인된다.

~$ bg

bash: bg: current: no such job

~$ gedit


그리고, CTRL+Z를 누른다. 그러면, 다음과 같이 명령을 입력할 수 있다. 그러나, gedit GUI는 먹통이된다.

^Z

[1]+  Stopped                 gedit

~$


아래와 같이 실행하여 background인 gedit process를 시작시킨다. 이렇게 되면 gedit GUI가 사용가능하다.

~$ bg 1

[1]+ gedit &

~$


아래와 같이 실행하면 foreground로 전환되어, 기존의 gedit를 실행한것과 동일하게 block된 상태가 된다.

~$ fg 1

gedit


CTRL+C를 누르면 Kill된다. gedit 창은 종료된다.

^C

~$


앞선 예의 bg나 fg의 1은, 처음 ^Z될때 알려진 번호가 사용된다.


이제 다음과 같이 jobs 명령을 이용할 수 있다.

~$ gedit&

[1] 4121

~$ gcalctool&

[2] 4124

~$ jobs

[1]-  Running                 gedit &

[2]+  Running                 gcalctool &

~$ jobs -l

[1]-  4121 Running                 gedit &

[2]+  4124 Running                 gcalctool &

~$ jobs -l %2

[2]+  4124 Running                 gcalctool &

~$

gedit와 gcalctool 실행시 &를 추가하여 background로 실행한다. jobs를 통해 [1], [2] job을 확인할 수 있다. [2]에 +가 있음으로, 2번이 current job이 된다. job 번호를 명시하지 않는 경우, current job 번호가 기본값이 된다. -l 옵션을 사용하여 PID 확인이 가능하다. 뒤에 %2를 추가하여 해당 job만 확인할 수 있다.


~$ disown %2

~$ jobs -l

[1]+  4121 Running                 gedit &

~$

위와 같이 disown을 실행하여 shell과 분리할 수 있다. 이렇게 되면 shell이 종료되더라도 해당 job은 계속 실행될 수 있다.


~$ disown -h

~$ jobs -l

[1]+  4121 Running                 gedit &

~$

위 명령은, 현재 shell에서 보내진 HUP signal로 부터 보호하는 동작을 한다.


그리고 아래는 모든 job을 현재 shell로 부터 분리하는 것이다.

~$ disown -a

~$ jobs -l

~$


Process Kill과 Signal


process에 signal을 전달하여 동작을 중단하거나 변경할 수 있다. kill 혹은 killall은 process를 종료하기 위해 signal을 전달한다. signal은 다음과 같이 숫자나 문자로 표현된다.


 Signal 번호

 Singal 이름

 설명

 1

 SIGHUP

 terminal 종료 혹은 제어 process 종료

 2

 SIGINT

 키보드 인터럽트

 3

 SIGQUIT

 키보드 종료 (keyboard quit)

 4

 SIGILL

 비정상 명령 (illegal instruction)

 6

 SIGABRT

 중단 함수(abort function)로 부터 중단(abort) 전달

 8

 SIGFPE

 부동연산예외(floating point exception)

 9

 SIGKILL

 종료 signal

 11

 SIGSEGV

 잘못된 메모리 참조

 13

 SIGPIPE

 중단된 파이프 (파이프를 읽을 process가 없음)

 14

 SIGALRM

 알람 system call로 부터 timer signal

 15

 SIGTERM

 중단 signal (termination signal)

 30,10,16

 SIGUSER1

 사용자 정의

 31,12,17

 SIGUSER2

 사용자 정의

 20,17,18

 SIGCHLD

 child 종료 혹은 중단

 19,18,25

 SIGCONT

 process가 중단되었다면 진행

 17,19,23

 SIGSTOP

 process 중단

 18,20,24

 SIGTSTP

 terminal에 타이핑 중단

 21,21,26

 SIGTTIN

 background process로 부터 terminal 입력

 22,22,27

 SIGTTOU

 background process로 부터 terminal 출력


해당 process에 SIGTERM을 전달한다.

~$ gedit&

[1] 4350

~$ kill 4350

~$

[1]+  Terminated              gedit

~$


SIGKILL을 해당 process에 전달한다.

~$ gedit&

[1] 4353

~$ kill -9 4353

~$ 

[1]+  Killed                  gedit

~$


다음은 중단된 process를 재개한다.

CTRL+Z로 이뤄진 gedit의 GUI는 먹통이되는데, 이후의 SIGCONT로 인해 GUI가 다시 활성화된다.

~$ gedit

^Z

[1]+  Stopped                 gedit

~$ jobs -l

[1]+  4357 Stopped                 gedit

~$ kill -SIGCONT 4357

~$


job을 종료한다.

~$ gedit&

[1] 4365

~$ kill %1

~$ 

[1]+  Terminated              gedit

~$


gedit를 모두 종료한다.

~$ gedit&

[1] 4431

~$ gedit&

[2] 4434

~$ killall gedit

[1]-  Terminated              gedit

[2]+  Done                    gedit

~$


다음 명령으로 sendmail process가 다시 설정을 읽도록 한다.

~$ killall -SIGHUP sendmail


SIGKILL등은 비정상적인 상황을 만들 수 있다(데이터 유실). unix 시스템에서 SIGHUP signal은 terminal이 main frame으로 부터 disconnect될 때 발생하는 것으로 설계되었으나, sendmail 혹은 httpd 같은 daemon process는 SIGHUP를 설정을 다시 읽는 행동으로 연결하여 사용되기도 한다.


Shell로 부터 process 격리시키기


shell session이 종료되더라도 실행중인 process를 지속시키기 원한다면, 몇가지 방법이 있다. 우선, nohup 명령이 가능하다.


다음은 gedit를 shell과 분리하여 실행시킨다.

~$ nohup gedit &

[1] 4638

~$ nohup: ignoring input and appending output to `nohup.out'


~$


아래는 gcc를 높은 우선 순위로 shell과 분리하여 실행한다.

~$ sudo nohup nice -9 gcc file_lock.c &

[2] 4662

~$


Shell로 부터 process 격리시키기


현재 실행중인 shell session으로 부터 disconnect되더라도 계속 실행시키기 원한다면, 몇가지 방법이 있다. 그 중 하나가 아래와 같이 nohup를 이용하는 방법이다.


~$ nohup gedit &

[1] 3669

~$ nohup: ignoring input and appending output to `nohup.out'


~$ exit

nohup에 의해 실행이 block되기 때문에 보통 nohup로 실행시킬 명령에 &를 사용한다. 이렇게 생성된 process, 즉, gedit는 이후의 exit 명령이후에도 계속 실행된다. nohup로 실행하지 않은 일반적인 경우, shell이 exit되면 gedit도 함께 종료된다.


아래는 gcc를 높은 우선순위로 실행시키되 session 관계 없이 계속 실행시키도록 한다.

~$ sudo nohup nice -9 gcc file_lock.c &

[1] 3801

~$


이와 같이 nohup 명령은 보통 느린 CPU 혹은 dial-up 연결(연결된 상태가 비용이 많이 드는 경우)시 주로 사용된다. 오늘날은 screen 같은 명령에서 자주 사용되어, shell 연결이 끝어지더라도 session이 유지되도록 하는 것이다. 이는 이후 설명할 예정이다.


process 예약하기


cron 관련 명령을 이용하면 shell에 연결되지 않더라도 지정된 시간에 명령을 실행할 수 있다. at 명령은 설정한 시간에 명령을 실행하도록 한다.


~$ mkdir at_test

~$ cd at_test

~/at_test$ ls -la

total 8

drwxr-xr-x  2 greenfish greenfish 4096 2013-12-26 10:30 .

drwxr-xr-x 29 greenfish greenfish 4096 2013-12-26 10:30 ..

~/at_test$ at now +1 min

warning: commands will be executed using /bin/sh

at> ls > ls.txt

at> CTRL+D <EOT>

job 1 at Thu Dec 26 10:31:00 2013

~/at_test$ atq

1 Thu Dec 26 10:31:00 2013 a greenfish

~/at_test$ ls -la

total 8

drwxr-xr-x  2 greenfish greenfish 4096 2013-12-26 10:30 .

drwxr-xr-x 29 greenfish greenfish 4096 2013-12-26 10:30 ..

~/at_test$ atq

~/at_test$ ls -la

total 12

drwxr-xr-x  2 greenfish greenfish 4096 2013-12-26 10:31 .

drwxr-xr-x 29 greenfish greenfish 4096 2013-12-26 10:30 ..

-rw-r--r--  1 greenfish greenfish    7 2013-12-26 10:31 ls.txt

~/at_test$

위 예는 1 분뒤 명령을 실행하도록 at을 사용하고 있다. 중간, <EOT>를 위해 CTRL+D 키를 눌러야 한다. atq 명령을 사용하면 현재 at 명령으로 인한 작업 queue를 보여준다. 위 예는 같은 shell session을 사용하고 있지만, 중간에 exit한 상태에서도 ls.txt 파일은 생성된다.


batch는 시스템 부하가 0.8 이하인 경우 실행된다.

~$ mkdir batch_test

~$ cd batch_test/

~/batch_test$ batch

warning: commands will be executed using /bin/sh

at> ls > /home/greenfish/batch_test/ls.txt

at> <EOT>

job 4 at Thu Dec 26 10:36:00 2013

~/batch_test$ atq

~/batch_test$ ls -la

total 12

drwxr-xr-x  2 greenfish greenfish 4096 2013-12-26 10:37 .

drwxr-xr-x 30 greenfish greenfish 4096 2013-12-26 10:36 ..

-rw-r--r--  1 greenfish greenfish    7 2013-12-26 10:37 ls.txt

~/batch_test$


아래와 같이 atrm 명령으로 at 작업들을 삭제한다.

~$ at now +10 min

warning: commands will be executed using /bin/sh

at> ls > a.txt

at> <EOT>

job 5 at Thu Dec 26 10:53:00 2013

~$ at now +15 min

warning: commands will be executed using /bin/sh

at> ls > b.txt

at> <EOT>

job 6 at Thu Dec 26 10:58:00 2013

~$ atq

5 Thu Dec 26 10:53:00 2013 a greenfish

6 Thu Dec 26 10:58:00 2013 a greenfish

~$ atrm 5

~$ atq

6 Thu Dec 26 10:58:00 2013 a greenfish

~$


contab을 이용하여 반복적인 예약 작업을 실행할 수 있다. 다음과 같이 -e 옵션을 사용하여 개인용 crontab 파일을 생성할 수 있다.

~$ crontab -e

no crontab for greenfish - using an empty one


Select an editor.  To change later, run 'select-editor'.

  1. /bin/ed

  2. /bin/nano        <---- easiest

  3. /usr/bin/vim.tiny


Choose 1-3 [2]:

보통 vi editor가 실행되기도 하고, 위와 같이 editor를 선택하는 입력이 뜰 수 있다. 선호하는 editor를 선택하면 다음과 같은 파일을 설정할 수 있다.


# Edit this file to introduce tasks to be run by cron.

#

# Each task to run has to be defined through a single line

# indicating with different fields when the task will be run

# and what command to run for the task

#

# To define the time you can provide concrete values for

# minute (m), hour (h), day of month (dom), month (mon),

# and day of week (dow) or use '*' in these fields (for 'any').#

# Notice that tasks will be started based on the cron's system

# daemon's notion of time and timezones.

#

# Output of the crontab jobs (including errors) is sent through

# email to the user the crontab file belongs to (unless redirected).

#

# For example, you can run a backup of all your user accounts

# at 5 a.m every week with:

# 0 5 * * 1 tar -zcf /var/backups/home.tgz /home/

#

# For more information see the manual pages of crontab(5) and cron(8)

#

# m h  dom mon dow   command


위 파일 끝에 다음을 넣으면 매 10분에 ls 명령을 실행한다.

10 * * * * ls > a.txt


위 구문은 다음과 같다.

분 시 일 월 요일 명령

각 단위에 *를 사용하면 "어떤값"이라도 만족하겠다는 뜻으로, 위 예는 10분만 지정했기 때문에 매 10분에 해당 명령을 실행하게 되는 것이다.

각 단위는 ,를 사용하여 여러개 등록할 수 있다. 만일, 매 10분과 40분에 실행하고자 한다면, 다음과 같다.

10,40 * * * * ls > a.txt

또한 /를 사용하여 "마다"를 등록할 수 있다. 만일 10분 마다 실행하고자 한다면, 다음과 같다.

*/10 * * * * ls > a.txt

각 단위에 대한 설명은 다음과 같다.


 설명

 범위

 분

 0 ~ 59

 시

 0 ~ 23

 일

 0 ~ 31

 월

 1 ~ 12

 요일

 Mon(1), Tue(2), ..., Sat(6), Sun(0)

 명령

 반드시 한줄로 표현


10 * * * * ls > a.txt를 저장하고 나가면 다음과 같다.


...

Choose 1-3 [2]: 2

crontab: installing new crontab

~$


아래와 같이 crontab 파일의 내용을 확인할 수 있다.

~$ crontab -l

# Edit this file to introduce tasks to be run by cron.

# Each task to run has to be defined through a single line

# indicating with different fields when the task will be run

# and what command to run for the task

# To define the time you can provide concrete values for

# minute (m), hour (h), day of month (dom), month (mon),

# and day of week (dow) or use '*' in these fields (for 'any').# 

# Notice that tasks will be started based on the cron's system

# daemon's notion of time and timezones.

# Output of the crontab jobs (including errors) is sent through

# email to the user the crontab file belongs to (unless redirected).

# For example, you can run a backup of all your user accounts

# at 5 a.m every week with:

# 0 5 * * 1 tar -zcf /var/backups/home.tgz /home/

# For more information see the manual pages of crontab(5) and cron(8)

# m h  dom mon dow   command

10 * * * * ls > a.txt

~$


다음과 같이 다른 user의 crontab 파일을 작성할 수 있다.

~$ sudo crontab -eu root


현재의 crontab 파일을 삭제하려면 다음과 같다.

~$ crontab -r

~$