시스템이야기2008. 11. 19. 18:40
서버에 접속한 유저가 어떤 명령을 내렸는지 실시간으로 확인하려면 어떻게 해야할까? history file을 뒤진다? 이건 너무 불편하다. 명령이 실행될 때마다 특정이벤트를 발생해서, 별도 저장해주면 효과적일 것이다. 그 것도 syslog를 통해서 명령이 저장된다면 원격지 서버에서 특정 서버의 실행 명령을 모조리 확인해볼 수 있을 것이다.

몇줄의 쉘 function으로 syslog로 실행명령을 보내는 방법을 알아보자.

function logging
{
        stat="$?"
        cmd=$(history|tail -1)
        if [ "$cmd" != "$cmd_old" ]; then
                logger -p local1.notice "[2] STAT=$stat"
                logger -p local1.notice "[1] PID=$$, PWD=$PWD, CMD=$cmd"
        fi
        cmd_old=$cmd
}
trap logging DEBUG

위 스크립트에서 중요한 부분은 logger와 trap이다.

1) logger는 지정한 메시지를 syslog로 보내주는 명령이다.
   위에서는 local1 서비스종류(facility)과 notice 레밸로 syslog로 메시지를 보내준다.
   logger의 활용에 대해서는 '여러 서버의 load를 터미널에서 실시간 모니터링' (글 좋은진호, 2008.2)
   중 '2. 미리 준비되어 있어야할 사항' 부분을 살펴보기 바란다.
2) trap은 bash내부 명령으로 특정시그널이 발생할 때 지정한 명령어가 실행된다.
   형식) trap "명령" 시그널
   위에서는 DEBUG 형태로, 명령이 실행될 때마다 logging function을 호출한다.

위의 스크립트를 global하게 적용하려면 /etc/profile 에 추가하거나 /etc/profile.d/cmd_logging.sh 로 저장하면 된다. 유저별로 적용하려면 $HOME/.bash_profile 또는 $HOME/.bashrc에 넣어둔다. 이제 적용됐는지 로긴해보자.

Sep 30 17:11:32 cnx1 coffeenix: [2] STAT=0
Sep 30 17:11:32 cnx1 coffeenix: [1] PID=29168, PWD=/home/coffeenix, CMD=    7  ls -la
Sep 30 17:11:36 cnx1 coffeenix: [2] STAT=0
Sep 30 17:11:36 cnx1 coffeenix: [1] PID=29168, PWD=/home/coffeenix, CMD=    8  vi get_stat.sh
Sep 30 17:15:24 cnx1 coffeenix: [2] STAT=0
Sep 30 17:15:24 cnx1 coffeenix: [1] PID=29168, PWD=/home/coffeenix, CMD=    9  chmod 700 get_stat.sh
Sep 30 17:15:28 cnx1 coffeenix: [2] STAT=0
Sep 30 17:15:28 cnx1 coffeenix: [1] PID=29168, PWD=/home/coffeenix, CMD=   10  ./get_stat.sh
Sep 30 17:15:35 cnx1 coffeenix: [2] STAT=0
Sep 30 17:15:35 cnx1 coffeenix: [1] PID=29168, PWD=/home/coffeenix, CMD=   11  ls
Sep 30 17:16:31 cnx1 coffeenix: [2] STAT=0
Sep 30 17:16:31 cnx1 coffeenix: [1] PID=29168, PWD=/home/coffeenix, CMD=   12  cd /var/log
Sep 30 17:16:32 cnx1 coffeenix: [2] STAT=0
Sep 30 17:16:32 cnx1 coffeenix: [1] PID=29168, PWD=/var/log, CMD=   13  ls

시간표시를 자세히 보면 [2]가 먼저 저장되고, [1]이 그 다음에 저장된다. [2] 는 이전에 실행한 명령의 실행 결과 코드이며, [1]은 방금 실행한 명령이다. 방금 실행한 결과 코드는 다음 명령이 실행되어야 결과로 저장이 된다.

실행명령만 별도 로그로 저장하고 싶다면 /etc/syslog.conf 에 다음을 추가하고, syslogd 데몬을 재실행해주면 된다.

local1.notice                           /var/log/cmd.log

보다 자세한 것은 커피닉스에 써둔 '쉘에서 실행한 명령을 syslog로 자동 보내기'를 살펴보기 바란다.

Posted by 좋은진호