Centos 6.4 For Video Streaming

ถ้าพูดถึงระบบเซิฟเวอร์สำหรับ Video Streaming ที่ดีที่สุด คงหนีไม่พ้น Centos Nginx + Disk ที่ทำ RAID

เริ่มกันเลย

แก้ repos

nano /etc/yum.repos.d/linuxtech.repo

######################################################
[linuxtech]
name=LinuxTECH
baseurl=http://pkgrepo.linuxtech.net/el6/release/
enabled=1
gpgcheck=1
gpgkey=http://pkgrepo.linuxtech.net/el6/release/RPM-GPG-KEY-LinuxTECH.NET
######################################################


แก้เวลาเครื่องให้ตรง

#yum install ntp -y
#ntpdate pool.ntp.org
#chkconfig ntpd on
#service ntpd restart


หรือ

rm -f /etc/localtime
ln -s /usr/share/zoneinfo/Asia/Bangkok /etc/localtime


อับเดตุ

yum update -y


ติดตั้งสิ่งที่จะใช้งานเบื้องต้น

yum install -y gcc gcc-c++ pcre-devel zlib-devel libxml2 libxml2-devel libxslt libxslt-devel bzip2 bzip2-devel curl curl-devel libjpeg libjpeg-devel libpng libpng-devel gd gd-devel mysql mysql-devel mysql-server net-snmp net-snmp-devel freetype-devel libtool-ltdl-devel ncurses ncurses-devel libevent-devel pcre-devel zlib-devel patch wget nano make gcc gcc-c++ net-snmp net-snmp-utils iptraf


ติดตั้ง ftp

wget ftp://ftp.proftpd.org/distrib/source/proftpd-1.3.4b.tar.gz
tar xf proftpd-1.3.4b.tar.gz
cd proftpd-1.3.4b
./configure --sysconfdir=/etc
make
make install


ติดตั้งเสร็จต่อด้วย configuration ftp

ln -s /usr/local/sbin/proftpd /usr/sbin/proftpd


nano /etc/proftpd.conf

DefaultAddress 192.168.0.1
User                            nginx
Group                           nginx
DefaultRoot ~
RequireValidShell off
AllowStoreRestart on
AllowOverwrite on
AllowRetrieveRestart on
AuthUserFile /etc/proftpd/passwd


nano /etc/init.d/proftpd

#!/bin/sh
# $Id: proftpd.init,v 1.1 2004/02/26 17:54:30 thias Exp $
#
# proftpd        This shell script takes care of starting and stopping
#                proftpd.
#
# chkconfig: - 80 30
# description: ProFTPD is an enhanced FTP server with a focus towards \
#              simplicity, security, and ease of configuration. \
#              It features a very Apache-like configuration syntax, \
#              and a highly customizable server infrastructure, \
#              including support for multiple 'virtual' FTP servers, \
#              anonymous FTP, and permission-based directory visibility.
# processname: proftpd
# config: /etc/proftp.conf
# pidfile: /var/run/proftpd.pid

# Source function library.
. /etc/rc.d/init.d/functions

# Source networking configuration.
. /etc/sysconfig/network

# Check that networking is up.
[ ${NETWORKING} = "no" ] && exit 0

[ -x /usr/sbin/proftpd ] || exit 0

RETVAL=0

prog="proftpd"

start() {
        echo -n $"Starting $prog: "
        daemon proftpd
        RETVAL=$?
        echo
        [ $RETVAL -eq 0 ] && touch /var/lock/subsys/proftpd
}
stop() {
        echo -n $"Shutting down $prog: "
        killproc proftpd
        RETVAL=$?
        echo
        [ $RETVAL -eq 0 ] && rm -f /var/lock/subsys/proftpd
}

# See how we were called.
case "$1" in
  start)
        start
        ;;
  stop)
        stop
        ;;
  status)
        status proftpd
        RETVAL=$?
        ;;
  restart)
        stop
        start
        ;;
  condrestart)
        if [ -f /var/lock/subsys/proftpd ]; then
          stop
          start
        fi
        ;;
reload)
        echo -n $"Re-reading $prog configuration: "
        killproc proftpd -HUP
        RETVAL=$?
        echo
        ;;
  *)
 echo "Usage: $prog {start|stop|restart|reload|condrestart|status}"
        exit 1
esac
exit $RETVAL


พักจิบชาแล้วมาต่อกัน

รันตามนี้เลยเพื่อเคลียร์ และ start service

groupadd nginx
useradd nginx -g nginx
mkdir -p /etc/proftpd/
chkconfig proftpd on
service iptables stop
chmod u+x /etc/init.d/proftpd
service proftpd restart
chkconfig --levels 235 proftpd on


add user for ftp (สำหรับโยนไฟล์ใส่เครื่อง)

ftpasswd --passwd --file=/etc/proftpd/passwd --uid=500 --name=disk1 --home=/home/disk1/anime --shell=/bin/false
chown -R nginx:nginx /home
chmod 777 -R /home


edit fstab mount disk ที่เราเตรียมไว้

nano /etc/fstab

/dev/md124                /home/disk1             ext4    defaults,noatime,nodiratime     1 3
/dev/md125                /home/disk2             ext4    defaults,noatime,nodiratime     1 4


ติดตั้ง Nginx (เวอร์เก่า 1.2.4 กำลังดี เบาแรง)

wget http://www.nginx.org/download/nginx-1.2.4.tar.gz
tar xf nginx-1.2.4.tar.gz
cd nginx-1.2.4
./configure --with-http_stub_status_module --with-http_mp4_module --with-http_ssl_module --with-http_secure_link_module
make
make install


ติดตั้งเสร็จก็ Config ต่อได้เลยครับ

nano /usr/local/nginx/conf/nginx.conf

user  nginx;
worker_processes  16;
worker_priority -20;
timer_resolution 100ms;

error_log /dev/null crit;

worker_rlimit_nofile 60000;
events {
    worker_connections  51200;
    multi_accept on;
    use epoll;

}
http {
    include       mime.types;
    default_type  application/octet-stream;

    access_log /dev/null;

    sendfile on;
    tcp_nopush  on;

    keepalive_timeout  15;
    send_timeout 30s;
    reset_timedout_connection on;
    tcp_nodelay on;
    server_tokens off;

    limit_conn_zone $binary_remote_addr zone=six:10m;

server {
        listen       80;
        server_name  27.254.66.105;
        error_page 403 http://goo.gl/d6cbI1;
        location / {
            root   /home/www;
            index  index.html index.htm index.php;
        }
        location /nginx_status {
            stub_status on;
        }
        location ~ \.cgi$ {
            gzip off;
            include fastcgi_params;
            fastcgi_pass  127.0.0.1:8999;
            fastcgi_index index.pl;
            proxy_read_timeout 120;
            proxy_connect_timeout 120;
            fastcgi_param   PATH_INFO  "/monitorix-cgi";
            fastcgi_param  SCRIPT_FILENAME  /usr/share/monitorix$fastcgi_script_name;
        }
        location /monitorix {
            alias /usr/share/monitorix;
            index index.html index.htm;
        }
     }
server {
        listen 80;
        server_name www.series8-server.com series8-server.com;
        error_page 403 http://goo.gl/d6cbI1;
        location / {
            root /home;
            index index.html index.htm;
        }

        location ~ \.mp4$ {
            if ($http_user_agent ~ "Mozilla/5.0" ) { return 403; }
            mp4;
            mp4_buffer_size     1m;
            mp4_max_buffer_size 15m;
            root /home;
        }
    }
}


nano /etc/init.d/nginx

#!/bin/sh

# nginx - this script starts and stops the nginx daemin
#
#
#
# chkconfig:   - 85 15
#
# description:  Nginx is an HTTP(S) server, HTTP(S) reverse \
#
#               proxy and IMAP/POP3 proxy server
#
# processname: nginx
#
# config:      /usr/local/nginx/conf/nginx.conf
#
# pidfile:     /usr/local/nginx/logs/nginx.pid
#

#
# Source function library.
. /etc/rc.d/init.d/functions

# Source networking configuration.
. /etc/sysconfig/network

# Check that networking is up.
[ "$NETWORKING" = "no" ] && exit 0

nginx="/usr/local/nginx/sbin/nginx"
prog=$(basename $nginx)

NGINX_CONF_FILE="/usr/local/nginx/conf/nginx.conf"

lockfile=/var/lock/subsys/nginx

# do not edit, put changes in /etc/sysconfig/phpfastcgi
#[ -f /etc/sysconfig/phpfastcgi ] && . /etc/sysconfig/phpfastcgi

start() {
   # /usr/local/sbin/php-fpm start

    [ -x $nginx ] || exit 5
    [ -f $NGINX_CONF_FILE ] || exit 6
    echo -n $"Starting $prog: "
    daemon $nginx -c $NGINX_CONF_FILE
    retval=$?
    echo
    [ $retval -eq 0 ] && touch $lockfile
    return $retval
}

stop() {
    #/usr/local/sbin/php-fpm stop

    echo -n $"Stopping $prog: "
    killproc $prog -QUIT
    retval=$?
    echo
    [ $retval -eq 0 ] && rm -f $lockfile
    return $retval
}

restart() {
    configtest || return $?
    stop
    start
}
reload() {
    configtest || return $?
    echo -n $"Reloading $prog: "
    killproc $nginx -HUP
    RETVAL=$?
    echo
}

force_reload() {
    restart
}

configtest() {
  $nginx -t -c $NGINX_CONF_FILE
}

rh_status() {
    status $prog
}

rh_status_q() {
    rh_status >/dev/null 2>&1
}
case "$1" in
    start)
        rh_status_q && exit 0
        $1
        ;;
    stop)
        rh_status_q || exit 0
        $1
        ;;
    restart|configtest)
        $1
        ;;
    reload)
        rh_status_q || exit 7
        $1
        ;;
    force-reload)
        force_reload
        ;;
    status)
        rh_status
        ;;
    condrestart|try-restart)
        rh_status_q || exit 0
            ;;
    *)
         echo $"Usage: $0 {start|stop|status|restart|condrestart|try-restart|reload|force-reload|configtest}"
        exit 2
  esac      


รัน

chmod +x /etc/init.d/nginx
chkconfig nginx on
fuser -k 80/tcp
service nginx restart

ติดตั้งมอนิเตอร์ไว้เช็คการทำงานของระบบโดยรวม

ส่วนตัวชอบ monitorix 3.2.1-1

$rpm -Uvh http://dl.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm
$yum install -y rrdtool rrdtool-perl perl-libwww-perl perl-MailTools perl-MIME-Lite perl-CGI perl-DBI perl-FCGI fcgi-perl smartmontools perl-XML-Simple
$rpm -Uvh http://www.monitorix.org/old-versions/monitorix-3.2.1-1.noarch.rpm
$mv /usr/share/monitorix/cgi-bin /usr/share/monitorix/monitorix-cgi


nano /usr/bin/fastcgi-wrapper.pl

#!/usr/bin/perl

use FCGI;
use Socket;
use POSIX qw(setsid);

require 'syscall.ph';

&daemonize;

#this keeps the program alive or something after exec'ing perl scripts
END() { } BEGIN() { }
*CORE::GLOBAL::exit = sub { die "fakeexit\nrc=".shift()."\n"; };
eval q{exit};
if ($@) {
    exit unless $@ =~ /^fakeexit/;
};

&main;

sub daemonize() {
    chdir '/'                 or die "Can't chdir to /: $!";
    defined(my $pid = fork)   or die "Can't fork: $!";
    exit if $pid;
    setsid                    or die "Can't start a new session: $!";
    umask 0;
}

sub main {
        $socket = FCGI::OpenSocket( "127.0.0.1:8999", 10 ); #use IP sockets
        $request = FCGI::Request( \*STDIN, \*STDOUT, \*STDERR, \%req_params, $socket );
        if ($request) { request_loop()};
            FCGI::CloseSocket( $socket );
}
sub request_loop {
        while( $request->Accept() >= 0 ) {
#processing any STDIN input from WebServer (for CGI-POST actions)
           $stdin_passthrough ='';
           $req_len = 0 + $req_params{'CONTENT_LENGTH'};
           if (($req_params{'REQUEST_METHOD'} eq 'POST') && ($req_len != 0) ){
                my $bytes_read = 0;
                while ($bytes_read < $req_len) {
                        my $data = '';
                        my $bytes = read(STDIN, $data, ($req_len - $bytes_read));
                        last if ($bytes == 0 || !defined($bytes));
                        $stdin_passthrough .= $data;
                        $bytes_read += $bytes;
                }
            }

            #running the cgi app
            if ( (-x $req_params{SCRIPT_FILENAME}) &&  #can I execute this?
                 (-s $req_params{SCRIPT_FILENAME}) &&  #Is this file empty?
                 (-r $req_params{SCRIPT_FILENAME})     #can I read this file?
            ){
        pipe(CHILD_RD, PARENT_WR);
        my $pid = open(KID_TO_READ, "-|");
        unless(defined($pid)) {
            print("Content-type: text/plain\r\n\r\n");
                        print "Error: CGI app returned no output - ";
                        print "Executing $req_params{SCRIPT_FILENAME} failed !\n";
            next;
        }
if ($pid > 0) {
            close(CHILD_RD);
            print PARENT_WR $stdin_passthrough;
            close(PARENT_WR);

            while(my $s = <KID_TO_READ>) { print $s; }
            close KID_TO_READ;
            waitpid($pid, 0);
        } else {
                    foreach $key ( keys %req_params){
                       $ENV{$key} = $req_params{$key};
}
                    # cd to the script's local directory
                    if ($req_params{SCRIPT_FILENAME} =~ /^(.*)\/[^\/]+$/) {
                            chdir $1;
                    }

            close(PARENT_WR);
            close(STDIN);
            #fcntl(CHILD_RD, F_DUPFD, 0);
            syscall(&SYS_dup2, fileno(CHILD_RD), 0);
            #open(STDIN, "<&CHILD_RD");
            exec($req_params{SCRIPT_FILENAME});
            die("exec failed");
        }
            }
else {
                print("Content-type: text/plain\r\n\r\n");
                print "Error: No such CGI app - $req_params{SCRIPT_FILENAME} may not ";
                print "exist or is not executable by this process.\n";
            }

        }
}


ให้สิทธิ์หน่อย

chmod +x /usr/bin/fastcgi-wrapper.pl


nano /etc/init.d/perl-fastcgi

#!/bin/sh
#
# nginx ??? this script starts and stops the nginx daemon
#
# chkconfig: - 85 15
# description: Nginx is an HTTP(S) server, HTTP(S) reverse \
# proxy and IMAP/POP3 proxy server
# processname: nginx
# config: /opt/nginx/conf/nginx.conf
# pidfile: /opt/nginx/logs/nginx.pid

# Source function library.
. /etc/rc.d/init.d/functions

# Source networking configuration.
. /etc/sysconfig/network

# Check that networking is up.
[ "$NETWORKING" = "no" ] && exit 0

perlfastcgi="/usr/bin/fastcgi-wrapper.pl"
prog=$(basename perl)

lockfile=/var/lock/subsys/perl-fastcgi

start() {
    [ -x $perlfastcgi ] || exit 5
    echo -n $"Starting $prog: "
    daemon $perlfastcgi
    retval=$?
    echo
    [ $retval -eq 0 ] && touch $lockfile
    return $retval
}

stop() {
    echo -n $"Stopping $prog: "
    killproc $prog -QUIT
retval=$?
    echo
    [ $retval -eq 0 ] && rm -f $lockfile
    return $retval
}
restart() {
    stop
    start
}
reload() {
    echo -n $???Reloading $prog: ???
    killproc $nginx -HUP
    RETVAL=$?
    echo
}


force_reload() {
    restart
}
rh_status() {
    status $prog
}
rh_status_q() {
    rh_status >/dev/null 2>&1
}
case "$1" in
    start)
        rh_status_q && exit 0
        $1
        ;;
    stop)
        rh_status_q || exit 0
        $1
        ;;
    restart)
     $1
        ;;
    reload)
        rh_status_q || exit 7
        $1
        ;;
    force-reload)
        force_reload
        ;;
    status)
        rh_status
        ;;
    condrestart|try-restart)
        rh_status_q || exit 0
        ;;
    *)
        echo $"Usage: $0 {start|stop|status|restart|condrestart|try-restart|reload|force-reload}"
        exit 2
esac


chmod +x /etc/init.d/perl-fastcgi
chkconfig perl-fastcgi on


nano /etc/monitorix.conf

#nano /etc/monitorix/monitorix.conf (ตำแหน่ง Part อีกที่ในกรณีอับ Cent)

our $PROC_MAX = "8";

"system"        => "Y",
        "kern"          => "Y",
        "proc"          => "Y",
        "hptemp"        => "N",
        "lmsens"        => "N",
        "nvidia"        => "N",
        "disk"          => "N",
        "fs"            => "N",
        "net"           => "Y",
        "serv"          => "N",
        "mail"          => "N",
        "port"          => "N",
        "user"          => "N",
        "apache"        => "N",
        "nginx"         => "Y",
        "lighttpd"      => "N",
        "mysql"         => "N",
        "squid"         => "N",
        "nfss"          => "N",
        "nfsc"          => "N",
        "bind"          => "N",
        "ntp"           => "N",
        "fail2ban"      => "N",
        "icecast"       => "N",
        "int"           => "N",


service รันๆ

service perl-fastcgi restart
service monitorix restart


ตั้งให้ monitorix รันเพื่อสร้างกราฟ

nano /etc/crontab (คำนวนเวลา crontab)

0 0 * * * root /usr/local/sync.sh
0 6 * * * root /usr/local/sync.sh
0 12 * * * root /usr/local/sync.sh
0 18 * * * root /usr/local/sync.sh
* * * * * root /usr/bin/curl "http://localhost/monitorix-cgi/monitorix.cgi?mode=localhost&graph=all&when=1day&color=black" > /dev/null

ถ้ามีหลายเซิฟเวอร์ มาแนะนำวิธีทำ sync ง่ายๆเหมือนปลอกกล้วย

ปกติแล้วถ้า มีการทำงานหนักๆ เราจะออกแบบระบบให้ทำงานแบบ mirror
mirror คือการกระจายเซิฟเวอร์ออกไป โดยมีข้อมูลเหมือนๆกัน เพื่อให้รองรับโหลดได้เพิ่มขึ้น


สร้าง key ที่เครื่องจะไปซิคเครื่องอื่น

ssh-keygen 


copy key เราไปใส่เครื่องปลายทาง เพื่อให้ตอน login ไม่ต้องกรอกข้อมูลเข้าระบบ

ssh-copy-id -i ~/.ssh/id_rsa.pub 192.168.1.1  


เซตค่าการ sync ปลายทางไปไหน คือ mirror 2 3 4

nano /usr/local/sync.sh (เครื่อง ปลายทาง ตามด้วยเครื่องหลัก)

#!/bin/sh
`/usr/bin/rsync -ar -e /usr/bin/ssh [email protected]:/home/disk1/* /home/disk1/ & > /dev/null`
`/usr/bin/rsync -ar -e /usr/bin/ssh [email protected]:/home/disk2/* /home/disk2/ & > /dev/null`


ให้สิทธิไฟล์ sync.sh

chmod +x /usr/local/sync.sh


แก้ไฟล์เสร็จ รัน restart crond service ทีนึงให้มัน apply ด้วยคำสั่ง

sudo systemctl restart crond.service


คำสั่งสำหรับการเช็ค ค่าใน mirror ให้ตรงกัน

rsync -avz -e ssh /home/disk1/* [email protected]:/home/disk1/

เพิ่มเติมลองไปดูในนี้ครับ

How to Setup Rsync with SSH on UNIX / Linux (rsync without password)

http://www.thegeekstuff.com/2011/07/rsync-over-ssh-without-password/

เทคนิคต่างๆ เพิ่มเติม

ตามแก้ไฟล์ตอนย้ายไป ip อื่น

ตามแก้ให้ครบ

nano /proc/sys/kernel/hostname
nano /etc/sysconfig/network
nano /usr/local/nginx/conf/nginx.conf
nano /etc/monitorix.conf
nano /etc/proftpd.conf


nano /usr/local/sync.sh
ssh-keygen
ssh-copy-id -i ~/.ssh/id_rsa.pub 192.168.1.1


แก้เสร็จก็ restart

service nginx restart
service perl-fastcgi restart
service monitorix restart
service proftpd restart


คำสั่งแก้ไข ip

nano /etc/sysconfig/network-scripts/ifcfg-eth0
/etc/init.d/network restart
or
service network restart


Block IP Address มันจะมีพวกชอบยิงๆ ddos block ซะ ดูจาก iptraf หรือ log

nano /etc/sysconfig/iptables

iptables -A INPUT -s 203.170.225.149 -j DROP
service iptables save
service iptables restart


Change SSH Port

nano /etc/ssh/sshd_config

แก้บรรทัด #Port 22 เป็น port อื่น เช่น 9218
service sshd restart


Download FTP on Centos โหลดมันทั้งโฟลเดอร์ และไฟล์ซับโฟลเดอร์ด้านใน

nohup wget -m --ftp-user=ratanon --ftp-password=xxxxxx ftp://192.168.1.1/disk1/*


แก้ออกเน็ทไม่ได้

nano /etc/resolv.conf


Configure The Firewall

$system-config-firewall-tui


ถ้าจะให้ WinSCP เข้าทาง root ได้ก็ต้องไปแก้ไขไฟล์ sshd_config (ในกรณีต้องเข้าผ่าน su root)

nano /etc/ssh/sshd_config
แก้ไข เอา # ออก แก้เป็น PermitRootLogin yes 
/etc/init.d/sshd restart


แก้ปัญหา Yum ไม่ได้ ติด Pid

nano /var/run/yum.pid


ป้องกันการลบไฟล์

chattr +i Filename]

ปลอดล็อก chattr -i [Filename]

เขียนไปเรื่อย ถ้าใครหลงเข้ามาอ่าน อยากได้เซิฟเวอร์เทพๆเบาๆ ไว้ทำสติมมิ่งก็ลองอ่านดูครับ มีไรก็ถามได้ช่วงนี้ไม่ค่อยได้จับเท่าไร ไปหนักกับการเขียนโปรแกรมซะส่วนใหญ่

0
312