Media Log

가끔 접속자가 많은 서버를 운영하다 보면 갑자기 웹 접속이 되지 않거나 접속이 너무 느려
아파치 데몬 개수를 확인해 보면 httpd가 256개나 떠 있는 경우가 있다.

그럼 먼저 웹서버가 갑자기 느려질 경우를 보자.
기본적으로 아파치 웹 서버의 경우 Max Clients가 256으로 설정되어 있어 동시에
256개의 데몬이 뜨게 되면 더 이상의 접속을 받아들이지 않고, 기존의 프로세스가
죽을 때까지 대기한 후 접속이 끊기게 되면 그제서야 접속을 받아들이게 된다.

따라서 동시 접속이 많은 경우에는 이전의 웹 접속이 끊길 때까지 대기해야 하므로 접속 속도가
느린 것처럼 느끼게 되는 것이다. 아래의 명령으로 동시접속을 체크 해보자

# netstat -anp | grep :80 | grep ESTAB | wc -l

또, 일반적으로 정상적인 접속의 경우에 256개의 프로세스가 모두 뜨는 경우는 그리 많지 않기에
현재의 상태가 비정상적인 접속인지 여부를 판단해야 한다.
이를 판단할 수 있는 방법은

# netstat -na | grep ES

ESTABLISHED된 연결 상태를 확인하여 클라이언트의 IP가 정상적인 연결인지 여부를 확인하면 된다. 또는

# netstat -na | grep ES | awk '{print $5}' | sort

클라이언트의 IP만 따로 확인해 봐도 된다.

통상적으로 HTTP 1.1 규약에서부터 적용되기 시작한 KeepAlive 기능을 지정하였을 경우
한 클라이언트 IP에서 동시에 3~5개 정도의 ttp 프로세스를 생성하므로 한 IP에서 3~5개 정도의
프로세스를 생성하는 것은 정상적인 현상이다. 그렇지 않고 여러개의 프로세스가 떠 있다면
비정상적인 접속 또는 부하를 일으키는 원인을 찾아봐야 할 것이다.

일단 top 명령을 이용하여 CPU 점유를 많이 하고 있는 프로세스들을 찾아야 할 것이다

# top -d 2

또는 잘못 짜여진 cgi 프로그램으로 인하여 시스템의 메모리를 몽땅 소비하는 프로그램이
실행 되고 있는지 살펴봐야 한다.

그리고 웹집이나 텔레포드 등의 로봇들이 접근하면 시스템은 현저하게 느려질 것 이다.
이러한 점들도 대비하여야 한다. 또한 스트리밍 서비스로 인한 부하도 점검해봐야 할 것 이다.

이번에는 웹서버가 정지되는 경우를 살펴보자.
MaxClient 에 걸려 서버가 정지되는 경우가 발생 할 수 있다.
참고로 엊그제 새벽에 한참 맛있게(?) 자고 잇는데 이런 경우를 당했다 ㅡㅡ;

MaxClient 수치는 아파치 소스코드에서 초기 설정값이 설정되어 있기 때문에 아무리 수치를 올려
설정을 하여도 아파치 웹서버는 동시에 httpd 데몬은 256개 이상 생성할 수 없다.
동시에 256개의 데몬이 뜨게 되면 더 이상의 접속을 받아들이지 않고, 기존의 프로세스가
죽을 때까지 대기한 후 접속이 끊기게 되면 그제서야 접속을 받아들이게 된다.

그럼 어떻게 해야 할 것인가?

일단은 아파치 세팅 시 Max Client 수치를 올리도록 소스코드를 수정하면 된다.
아파치 소스를 보면 src/include 안에 httpd.h 라는 헤더파일이 있는데 HARD_SERVER_LIMIT
값이 256으로 정의되어 있다.

#ifndef HARD_SERVER_LIMIT
#ifdef WIN32
#define HARD_SERVER_LIMIT 1024
#elif defined(NETWARE)
#define HARD_SERVER_LIMIT 2048
#else
#define HARD_SERVER_LIMIT 256
#endif
#endif

윈도우는 1024 넷웨어는 2048 기타는 256으로 설정이 되어있는것을 볼 수 있다. 리눅스는 기타에 속한다..ㅋㅋㅋ
그럼 256의 수치를 변경한 다음 컴파일 하면 된다. 이것은 수치는 시스템 사양에 따른 적절한
조절이 필요하다. 되도록 4의 배수로 수치를 조정하길 바란다.

일단 셋팅을 이렇게 하였다면 적어도 Max Clients 에 걸려 웹서버가 정지당하는 일은 없을것이다.
하지만 그냥 귀차니즘으로 인하거나 서버사양이 좋지 않아 디폴트로 셋팅하였다면
아파치 설정파일에서 소한의 설정을 하여야 한다.

이는 웹서버가 느려지는 것과 다운되는 것에 대한 최소한의 노력이라고 생각하면 된다.

일단 Timeout 값의 수치를 변경하자.
이 값은 클라이언트에서 서버에 연결하엿을때 클라이언트와 서버간에 아무런 메세지가 발생하지
않았을 때 오류로 처리할 시간을 설정한 값이다.
보통 300으로 설정되어있다. 만약 네트워크 속도가 느리다면 수치를 조금 올려서 설정하는 것이 좋다.

다음은 MaxKeepAliveRequests 의 값을 수정하여야 한다.
이 값의 의미는 연결을 유지한체로 허용할 수 있는 최대 요구수를 나타낸다.
이 값이 0 이라면 제한하지 않는다는 의미가 되고 일반적으로 이 수치는 높게 설정하는 것이 좋다.

다음 KeepAliveTimeout 의 수치를 변경하자. 이 값은 동일한 방문자가 동일한 연결을 유지한 채로 다음
요청을 할 때 까지 연결을 유지한 채로 기다리는 시간을 허용하는 시간을 의미한다.
따라서 접속자가 많다면 클라이언트에서 설정시간내에 요청을 하지 않으면 연결을 끊음으로서 요청시
생성되었던 데몬을 Kill 할 수 있다.

이정도로 웹서버의 성능을 튜닝하엿다.
나머지 무한한 추가적인 기능은 각자 상황에 맞게 설정 할 수 있을것이다.

훈련 시스템에 접속하기 위한 아이디와 패스워드는 아래와 같습니다.
Question 52
> 훈련 시스템 접속 주소 : 211.241.82.54
> 해당 아이디(ID) : level52
> 해당 패스워드(PW) : passwd=52


IT 업체인 W사는 솔라리스 서버를 이용하여 사용자들의 홈페이지를 제작해주는
업체를 경영하였다. 1년 정도의 시간이 지나자 많은 사용자들이 서버에 입주했고
입주 업무가 폭주하다 보니 별도의 상담 업무만을 전담하는 직원을 두게 되었다.
상담원 이씨에게 사용자들의 id 개설 업무를 주었는데 팀장 황씨는 시스템의
다른 권한은 주고 싶지 않았다.
이에 대한 접근제어 역할을 제공하는 도구를 찾던 중 sudo라는 도구가 훌륭히 역할을
수행 할 수 있다는 것을 알았다.
sudo를 이용하여 상담자 이씨(id: user_admin)에게 useradd 명령어에 대한 권한을
주도록 설정하라.

SUDO
사용목적 : 관리자(root)가 특정 사용자(특정 그룹)에게 특정 명령(명령그룹)을 root계정으로 실행할 수 있는 권한부여

* 구성파일 : /etc/sudoers
1. 유저, 호스트, 커멘드를 정의 가능.
2. 유저, 호스트, 커멘드의 엘리어스도 지정 가능
3. 구조
user host=commads
user : 로그인 id나 엘리어스 네임
host : hostname, 엘리어스 호스트네임
commads : 콤마로 구분되어지는 명령어 리스트 

더 자세한 내용은 관련자료를 참고 

사용법을 간단히 알아보자.  

# rpm -q sudo 를 실행하여 sudo가 설치되어 있는지 확인하자.
# vi /etc/sudoers 설정파일을 열어서
root ALL=(ALL) ALL
bob ALL=/usr/local/resin/bin/httpd.sh, /usr/local/apache/bin/apachectl  

일반 계정자 bob에게 resin의 httpd.sh명령과 apachectl명령 권한을 허용한 예이다. 
이제 일반계정 bob으로 위의 명령을 실행하려면

# su bob
$ sudo /usr/local/apache/bin/apachectl restart

이때 password를 물어보면 bob의 password를 입력하면 root권한으로 실행이 된다. 

풀이방법 
vi /etc/sudoers       ->sudoers파일 편집
user_admin      ALL=/usr/sbin/useradd      -> user_admin 에게 /usr/sbin/useradd 권한 설정
[출처] sudo를 이용한 특정사용자에게 특정 명령어에 대한 권한 부여 |작성자 오팔

Crontab

cron등록하는 방법 순서대로 하면 됩니다.

1.whereis php 명령어로 php가 있는 곳의 위치를 확인한다.
2.crontab -e 명령어로 작업을 추가한다.
예)*/5 * * * * /usr/bin/php -q /var/www/html/test.php
5분마다 php를 이용해서 해당 위치의 파일을 실행시키는 거다.
3.test.php의 소스안에서는 include파일같은것은 실제 경로를 써준다.
4./etc/rc.d/init.d/crond restart
5.crontab -l 명령어로 제대로 등록이 되었는지 살펴본다.
6.tail /var/log/cron 명령어로 5분마다 제대로 실행이 되었는지 로그를 검사한다.

___________________________________________________________________________________________
 1. cron이란 :
   일정시간 마다 시스템에서 자동으로 실행 시키는 데몬입니다.

 2. cron 데몬의 실행과 종료
   실행 : /etc/rc.d/init.d/crond start
   종료 : /etc/rc.d/init.d/crond stop

 3. crond 설정
  크론(cron)의 설정은 /etc/crontab에서 합니다.

  옵션

  -e : 설정된 파일을 새롭게 편집

  -d : 등록된 내용을 삭제

  -l  : 현재 등록된 내용을 본다

  4. crontab 파일 형식
 ----------    ----------  ---------------------------------------------------
  필  드                 의  미           범  위
 ----------    ----------  ---------------------------------------------------
 첫 번째                      분              0-59
 두 번째                      시              0-23
 세 번째                      일              0-31
 네 번째                      월              1-12
 다섯 번째                  요일             0-7 (0 또는 7=일요일, 1=월, 2=화, ...)
 여섯 번째                명령어             실행할 명령을 한줄로 쓴다.
 ----------    ----------  ---------------------------------------------------

 - 모든 엔트리 필드는 공백으로 구분된다.
 - 한 줄당 하나의 명령 (두줄로 나눠서 표시할 수 없음)
 - # 으로 시작하는 줄은 실행하지 않는다.

 - '*'표시는 해당 필드의 모든 시간을 의미한다.
 - 3,5,7와 같이 콤마(,)로 구분하여 여러 시간대를 지정할 수 있다.
 - 2-10와 같이 하이픈(-)으로 시간 범위도 지정할 수 있다.
 - 2-10/3와 같이 하이픈(-)으로 시간 범위를 슬래쉬(/)로 시간 간격을 지정할 수 있다(2~10시까

    지 3시간 간격으로. 즉, 3, 6, 9시를 의미함).

[출처] 주기적인 스크립트 실행을 통한 crontab 설정 문제 |작성자 오팔

crontab이란 예약된 작업을 실행하는 파일이다.
위치 :

/etc/crontab


옵션 :

crontab test1.sh(test1작업을 예약)
crontab -l (현재 걸려 있는 작업 목록 표시)
crontab -r (작업목록을 비움)
crontab -e (새로운 작업 입력,수정,삭제)

그럼 이제 등록할 파일에 대해 알아보자. 일반적으로 shell프로그래밍 한 파일을 넣으면 된다.
형식 :
[분] [시] [일] [월] [요일] [실행명령] [>|>>출력지정]

*/30 * * * * /usr/local/apache/htdocs2/start_cms2.sh > /dev/null
또는
30 * * * * /usr/local/apache/htdocs2/start_cms2.sh
(매 시간 30분마다 작업을 수행하고 결과는 출력하지 않는다)

45 */3 * * 1-5 /usr/local/apache/htdocs2/tart_cms.sh > /dev/console
(월~금요일 매 3시간 45분에 작업을 수행하고 결과는 화면에 출력한다)

* * * 3-5 * /usr/local/apache/htdocs2/tart_cms.sh >> /usr/local/apache/htdocs2/cms.log
(3월~5월까지 매시간 매분에 작업을 수행하고 결과는 cms.log파일에 추가한다)

여기서 주의할 점은 예약된 명령이 하나만 받아들여 지는데 이때문에 명령을 직접 넣지 않고 shell programming을 해주는 것이다.친구의 조언에 따르면 명령 && 명령 && 명령 이런 식도 먹힌다고 한다.

cron 사용법
linux]#vi /etc/crontab

분 시 날짜 달 요일 권한 command 형식으로 입력해줌...

ex) 05 * * * * root /home/html/update.php   -> 매시 5분에 update.php문 실행
ex) 05 15 * * * root /home/html/update.php   -> 매일 오후 3시 5분에 update.php문 실행

update.php

#!/usr/bin/php -q   (이건 리눅스에서 whereis php 해서 나오는 경로를 적어준다.) 
<?
 $conn=mysql_connect("localhost","user","password");
 mysql_select_db("edumeca",$conn);

 mysql_query("update tablename set updatefield=updatefield+1");
?>

update.php 의 실행권한을 준다.
linux]#chmod +x /root/home/html/update.php

이렇게 하면 지정한 시간에 php파일 실행...
php파일이 실행되었는지 볼려면

linux]#vi /var/log/cron


ps ax | grep httpd | wc -l   -> http로 접속한 프로세스
netstat -anp | grep :80 | grep ESTAB | wc -l  -> 아파치에 접속한 사용자 수
netstat -anp | grep :80 | wc -l   -> 아파치에 접속한 사용자수 위에 꺼랑 무신 차이지??

CPU 정보 (uname)

   # uname -p  ;i686은 펜티엄4를 의미
   # uname --help

메모리 정보 (free)

   # free -m  ;MB단위
   # free -k   ;KB단위

프로세스 정보 (ps, pstree)

   # ps auxw | grep httpd
   # pstree

프로세스별 CPU와 메모리 점유율 (top)

   # top          ;시스템이 갑자기 느려졌을 경우 사용

 - 주요 영역별 의미
    PID : 프로세스 ID
    USER : 소유주
    SIZE : 데이터 크기 (단위 KB)
    %CPU : CPU 점유율(%)
    %MEM : 멤리 점유율(%)

 - 종료 : q

마운트한 파일시스템의 정보 ( df)

 - 마운트한 파일시스템의 전체크기,사용한 공간, 여유공간 등의 정보
   # df -u

디렉토리별 용량 (du)

 - 각 디렉토리별 용량 확인
   # du --max-depth=1 -h /home  ;사용자별 디스크 사용현황

사용중인 장치정보(lsdev)

 - 시스템에서 인식하고 있는 장치(DMA, IRQ, I/O 포트 등)의 정보
   # lsdev

 - 세부적인 정보확인   ;/etc/sysconfig/hwconf 파일
 

현재 시스템 자용자 정보 (w)

 - 사용자명, 사용중인 터미널 사용중인 명령어 등의 현황
   # w

시스템에 설정된 시간 (date, rdate)

   # date                      ;현재 시간
   # rdate -s time.bora.net    ;표준 시간을 가져옴
   # clock                     ;CMOS의 시간
   # clock -w                  ;현재시간을 CMOS에 덮어 씀

   ※ 부팅시마다 rdate 로 정확한 시간을 가져와서 CMOS에 덮어쓰기 위해서는 /etc/rc.local을 편집

       # rdate -s time.bora.net
       # clock -w

       을 추가한다.

시스템에 연결된 소켓 정보

   # netstat

최근 시스템 접속자 정보

   # last

네트워크 장치 설정 정보

   # ifconfig

IP 주소 변경 방법 1 , 임시변경

   # ifconfig eth0 down == # ifdown eth0
   # ifconfig eth0 inet <new-ip> netmask <netmask>
   # ifconfig eth0 up == #ifup eth0
   # ifconfig eth0

 

IP 주소 변경 방법 2

   #redhat-config-network      ;에서 설정을 변경한 후 네트웍 서비스 재시작 ( # service network restart) 을 해줘야 한다.

 

IP 주소 변경 방법 3

   /etc/sysconfig/network-scripts/ifcfg-eth0 파일을 vi로 편집     ; 네트웍 서비스 재시작

[출처] 리눅스 시스템 설정과 자원사용 현황|작성자 테슬라