Category: Linux (OS, shell script, etc)

  • Ubuntu NAT Router

    เพื่อนครูที่โรงเรียนหนึ่งสอบถามเข้ามาว่ากำลังจะทำ Linux Router ด้วย Ubuntu 12.04 ผมก็มีอยู่ตัวหนึ่งที่ใช้ใน workshop อยู่พอดี ผมติดตั้ง Ubuntu 12.04 ที่มี network interface card จำนวน 2 อัน ทำอยู่ใน Oracle VM VirtualBox ผมติดตั้ง BIND โปรแกรมสำหรับทำ DNS server และ ISC-DHCP-SERVER โปรแกรมสำหรับทำ DHCP server เอาไว้ใช้ในการทดสอบเมื่อมี VM Guest เครื่องอื่นๆอยู่ภายใน internal network ไม่ต้องไปรบกวน IP Address ของสำนักงาน เพราะเครื่อง Guest อื่นๆ จะขอ DHCP IP จาก Ubuntu Router นั่นเอง แล้วยังสามารถตั้งชื่อโดเมนเนมให้กับเครื่อง Guest ได้อีกด้วย ในกรณีที่เราทำใช้งานใน Oracle VM VirtualBox นั้น network interface eth0 ก็ตั้งค่า Network Adapter เป็น NAT และ network interface eth1 ก็ตั้งค่า Network Adapter เป็น Internet Network ตั้งชื่อว่า Intnet1 แต่หากนำไปติดตั้งเป็น Linux Router สำหรับโรงเรียนด้วยเครื่องจริง network interface eth0 ก็เป็น IP Address ที่ได้รับจาก ADSL หรือ Leased Line ส่วน network interface eth1 ก็ตั้ง IP Address ตามใจชอบ

    ubuntu-nat-router

    ผมจึงคิดว่าก็น่าจะลองเขียนเป็นคำแนะนำส่งให้กับครูท่านนั้น แต่เพื่อให้สามารถต่อยอดต่อไปอีกได้ ผมจึงเขียนสะสมไว้ในหัวข้อเรื่อง คือ Ubuntu NAT Router ที่ Link นี้ http://opensource.cc.psu.ac.th/Ubuntu_NAT_Router

    ผมจึงมาบอกเล่าให้เพื่อนๆฟังครับ เผื่อว่าใครกำลังมองหาวิธีการนี้อยู่

  • 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

  • update ownCloud new version (5.0.6 to 5.0.7)

    หลังจากวันก่อนเมื่อช่วงต้นเดือนเขียนบทความ เรื่อง “มาทำ Self-hosted cloud storage ด้วย ownCloud ใน PSU กันเถอะ” ผมก็ทดสอบการใช้งานไปเรื่อยๆ มีเพื่อนชาว PSU sysadmin มาร่วมกันทดสอบกัน 5-6 คน ซึ่งเป็นเวอร์ชั่น 5.0.6 มาวันนี้เมื่อเข้าในหน้า admin ก็จะพบว่ามีแจ้งเตือนว่ามีเวอร์ชั่นที่ใหม่กว่าแล้ว คือ 5.0.7 แล้ว ก็ทำการอัปเดตผ่านหน้าเว็บได้เลย ถ้ากำหนด file permission ให้แก่ webserver user (www-data) ที่ไดเรกทอรี /var/www/owncloud

    owncloud-update-01

    ผลลัพธ์คือเมื่ออัปเดตเสร็จจะพบว่าเข้าสู่โหมด maintenance

    owncloud-update-02

    เราในฐานะผู้ดูแลต้องไปปลดล็อกที่ไฟล์ config.php ด้วยครับ จากนั้นก็จะใช้งานได้แล้ว

    ย้อนสักนิด การติดตั้ง owncloud นั้นจะมีอยู่ 3 วิธี คือ Tar or Zip File เหมาะสำหรับมีเครื่อง server เอง, Web Installer เหมาะสำหรับ shared hosting และสุดท้ายคือ Linux packages เหมาะสำหรับอัปเดตแบบอัตโนมัติเมื่อทำ apt-get update และ apt-get upgrade นั่นเอง

    owncloud-installation-webpage

    วิธีที่ผมเลือกติดตั้งคือแบบ Tar File เอามาลงในเครื่อง server เอง ดังนั้นเมื่อมีอัปเดตเวอร์ชั่นใหม่ เราจะควบคุมเองได้ว่าจะทำเมื่อไร หลังจากทราบว่ามีเวอร์ชั่นใหม่ แตกต่างจากแบบ Linux packages ซึ่งจะอัปเดตไม่รอเรา อาจทำให้มีปัญหาได้หากเรามีการ manual ปรับปรุงไฟล์ php บางไฟล์ เช่นที่ผมทำคือต้องมีการแก้ไขไฟล์ ftp.php, base.php และ app.php ดังนั้นวันนี้ผมจึงมาบอกเล่าให้ฟังว่า การอัปเดตจากเวอร์ชั่นหนึ่งไปอีกเวอร์ชั่นหนึ่งแบบเล็กน้อย เรียกว่า update นะครับ และหากเป็นการเปลี่ยนแปลงใหญ่ จะเรียกว่า upgrade อันนี้อ่านมาจากเว็บ ownCloud ซึ่งวิธีการทำจะแตกต่างกัน

    วันนี้มาแนะนำวิธีการอัปเดต (update) ownCloud จากเวอร์ชั่น 5.0.6 ไปเป็น 5.0.7 ซึ่งหลังจากอัปเดตตามเค้าว่าแล้ว ผมก็มาปรับแต่งเพื่อให้เข้ากันกับ PSU อีกที ผมจึงเขียนเป็น wiki ไว้ที่เว็บ opensource.cc.psu.ac.th เรื่อง อัปเดต owncloud (5.0.6) เป็นเวอร์ชั่นสูงกว่า (5.0.7) สำหรับ PSU ซึ่งมีรายละเอียดการทำงานเป็นขั้นตอน โดยสรุปพบว่า เวอร์ชั่นใหม่นี้ยังไม่ได้แก้ไข bug ที่พบในไฟล์ 3 ไฟล์ที่จำเป็นสำหรับ PSU ครับ

  • มาทำ Self-hosted cloud storage ด้วย ownCloud ใน PSU กันเถอะ

    เมื่ือช่วงต้นเดือนพฤษภาคม ผมได้รับอีเมลเกี่ยวกับรายชื่อ cloud storage ที่มีให้บริการ เช่น dropbox เป็นต้น แล้วมีพูดถึงว่านอกจากบริการบนอินเทอร์เน็ต ยังมี open source software ชื่อ owncloud อีกตัวนึงที่มีคนทำไว้ใช้งานเองและใช้ได้จริง และเป็นที่นิยมกันมากมาย ผมเลยตามไปดูที่ owncloud.org และก็จุดประกายความคิดขึ้นมาต่อยอดจากที่งาน WUNCA26 ว่ามีอาจารย์ท่านนึงบรรยายเกี่ยวกับ cloud ว่าอยากให้มหาวิทยาลัยมี private cloud ใช้งาน อันนี้ก็เป็นอันหนึ่งคือ self-hosted cloud storage หมายถึง ตั้งเซิร์ฟเวอร์เองไว้เก็บไฟล์
    owncloud-in-psu-1
    owncloud ทำอะไรได้บ้าง ผมจินตนาการอย่างนี้นะครับ ผมจะมี directory เก็บไฟล์ทำงาน ซึ่งแน่นอนอาจต้องการอีกสักหนึ่งเพื่อไว้กิจกรรมอะไรก็ได้ และนำไฟล์เหล่านี้ไปเก็บบน server ทำให้ผมจะมีข้อมูลเก็บอยู่สองแห่ง (เครื่องผมและserver)  เมื่อผมแก้ไข เพิ่ม หรือ ลบไฟล์ แล้วจะมี sync client สักตัวทำการ sync ให้เท่ากัน เมื่อผมไม่ได้ใช้เครื่องคอมฯของตนเอง ผมก็สามารถเข้าเว็บเบราว์เซอร์แล้วเข้าไปที่ URL ที่กำหนดไว้ เช่น [ http://cloud.in.psu.ac.th ] เป็นต้น ผมก็สามารถ login เข้าทำงานกับไฟล์ของผมได้แล้ว จากนั้นก็คิดต่อไปว่าแล้วผมมี Android smart phone จะต้องใช้ได้ด้วย คือเปิดดูพวกไฟล์ pdf ได้เลย รวมถึงเมื่อถ่ายรูป ไฟล์รูปภาพก็จะอัพโหลดไปเก็บอยู่บน server ของผม และเมื่อผมกลับมาเปิดเครื่องคอมฯของตนเองอีกครั้ง โปรแกรม sync client ก็จะทำการ sync ไฟล์รูปภาพจาก server ลงมาเก็บไว้ใน directory ที่กำหนดไว้

    เป็นไงครับอ่านมาถึงตรงนี้ นึกออกแล้วใช่ไม๊ครับ ไม่เห็นภาพ ลองดูตัวอย่างจาก presentation เรื่อง คู่มือสำหรับผู้ใช้งาน ownCloud ครับ

    ตามนี้ [ https://sharedrive.psu.ac.th/public.php?service=files&t=494382205a552cc52f07e6855c991162 ]

    สองสัปดาห์ที่ผ่านมา ผมจึงลงมือทำการทดสอบ ติดตั้งง่ายครับใช้ ubuntu server 12.04.2 มีเรื่องที่ต้องสนใจ 2-3 เรื่อง เรื่องแรกคือจะใช้ฐานข้อมูลอะไร มีให้เลือก sqlite, MySQL, PostGresSQL เรื่องที่สองคือจะใช้ user name อะไรในการ login เข้าใช้งาน เรื่องที่สามคือจะกำหนดพื้นที่ดิสก์รวมอยู่กับ system หรือแยก partition ต่างหากสำหรับเก็บ data นอกจากนี้ก็เป็นการคอนฟิกเพิ่มเติมโปรแกรม (owncloud จะเรียกว่า Apps) เช่น Bookmark, News Feed, Web mail client เป็นต้น และสุดท้ายคือตั้งค่า disk quota สำหรับผู้ใช้แต่ละคน

    เริ่มต้นด้วยแบบง่ายๆก็ใช้ local user ของโปรแกรม owncloud เองเลย ซึ่งเก็บอยู่บนฐานข้อมูล sqlite ในขั้นตอนติดตั้ง แบบยากขึ้นมานิด จะใช้ External user support ได้อย่างไร ก็พบว่าทำได้จาก LDAP, IMAP, FTP server ผมเลือกใช้ FTP server เพราะว่าเราสามารถผสมใช้ linux user name พร้อมๆไปกับ PSU Passport ของมหาวิทยาลัยได้ด้วย ผ่านทาง FTP server และอนุญาตเฉพาะ user name ที่เป็นสมาชิกเท่านั้น ซึ่งเป็นความรู้ที่ได้รับจากหลวงพี่วิภัทรสั่งสอนไว้นั่นเอง คือ PSU-radius + vsftpd + pam_radius_auth

    ถัดมาก็ทดสอบเปลี่ยนไปใช้ MySQL database ก็ไม่ยุ่งยากอะไร คือ ต้องเตรียม database name, database user, database password ไว้ก่อน จากนั้นในขั้นตอนติดตั้งทางหน้าเว็บครั้งแรกให้เลือก Advanced เพื่อเลือกว่าจะใช้ MySQL แล้วระบุค่าสำหรับ database ที่เตรียมไว้นั้น

    ถัดมาก็ศึกษาวิธีการเปลี่ยนใช้ partition แยกต่างหากสำหรับ ownCloud data ซึ่งก็คือที่เก็บไฟล์ของ user แต่ละคนนั่นเอง หากให้คนละ 10 GB มีคน 100 คน ก็ต้องใช้ 1,000 GB เป็นต้นจึงจำเป็นต้องแยก mount disk ต่างหาก ตรงนี้จะเกี่ยวกับไฟล์ /etc/fstab ด้วยนะ นอกจากนี้ผมต้องการให้มีการ share with link เพื่อให้สาธารณะดูไฟล์ได้โดยผมจะส่งเป็นอีเมลไปให้ จึงต้องคอนฟิกเรื่อง mail อีกนิด

    การติดตั้งหลักๆเสร็จไปแล้ว ต่อมาก็ทดสอบการใช้งาน เริ่มต้นจากเมื่อ login เข้าใช้งานครั้งแรก จะมีหน้าต่าง wizard เชิญชวนให้ติดตั้ง Desktop Client ซึ่งมีสำหรับ Linux, Windows, Mac OS ซึ่งฟรีครับ นอกจากนี้ก็มีสำหรับ Android PlayStore, iOS AppStore แต่เนื่องจากต้องมีค่าใช้จ่ายสำหรับดาวน์โหลดทาง PlayStore และ AppStore ราคา 29 บาท ผมจึงเสาะหาพบว่า “ฟรี” ที่นี่ครับ [ http://f-droid.org ]จะมีโปรแกรม owncloud client ให้ใช้ฟรีๆครับ

    ทดสอบการใช้งาน พบว่ามี bug 2-3 เรื่อง เรื่องแรกการ share file ระหว่าง user name บน ownCloud กับ External user ยังไม่สมบูรณ์ จึงค้นหา google พบว่ามีคนบอกวิธีแก้ bug ไว้ให้ และ bug เกี่ยวกับเกิดมี error log record ผิดปรกติจำนวนมากใน /var/www/owncloud/data/owncloud.log ซึ่งไม่ควรจะมี ผมพบว่ายังมี bug อีก 2 อย่างที่ยังแก้ไขไม่ได้คือ disk quota แสดงผลไม่ตรงความจริง คือ ผมอัพโหลดไฟล์ไว้มากๆเพื่อลองทดสอบประมาณ 7พันกว่าไฟล์ ขนาด 7 GB กว่าๆ แต่โปรแกรมรายงานเพียง 2GB เท่านั้น และอีก bug คือ Apps ชื่อ Pictures Gallery เมื่อผมลบไฟล์รูปภาพไปแล้ว แต่ thumbnail picture ยังคงเก็บอยู่ อันนี้ผมซอกแซกเข้าไปดูในที่เก็บ คือ cd /var/www/owncloud/data/(user)/gallery/

    หากต้องการทดสอบ ให้อ่านเรื่อง ติดตั้ง owncloud (5.0.6) บน ubuntu (12.04.2) สำหรับ PSU [ http://opensource.cc.psu.ac.th/ติดตั้ง_owncloud_(5.0.6)_บน_ubuntu_(12.04.2)_สำหรับ_PSU ] อยู่ที่เว็บไซต์ opensouce.cc.psu.ac.th ครับ

    และนี่คือ Your Private Cloud Storage in PSU ครับ ขอบคุณครับ

  • วิธีเอา index.php ของ Codeigniter ออกไป (Ubuntu/Linux Mint)

    1.สร้างไฟล์ .htaccess ในโปรเจกของท่าน ดำเนินใส่โค๊ดดังนี้ (สมมุติว่าเป็น /var/www/ci/)

    RewriteEngine on
    RewriteBase /ci/
    RewriteCond $1 !^(index\.php|assets|uploads|robots\.txt)
    RewriteRule ^(.*)$ index.php/$1 [L]

     

    2.เปิด  terminal และพิมพ์คำสั่ง เพื่อเปิด mod_rewrite

    sudo a2enmod rewrite

     

    3.เพิ่ม virtual host ใน /etc/apache2/sites-available/default

    sudo gedit /etc/apache2/sites-available/default

     

    4.เพิ่มโค้ดดังนี้

    <Directory /var/www/ci>
            Options Indexes FollowSymLinks MultiViews
                    AllowOverride All
                    Order allow,deny
                    allow from all             
    </Directory>

     

    5. Restart Apache

    sudo /etc/init.d/apache2 restart

     

    6.ไปที่โปรเจก codeigniter แก้ไขไฟล์  application/config/config.php เอา index.php ออก

    จาก $config[‘index_page’] = ‘index.php’;

    เป็น $config[‘index_page’] = ”;

  • การตรวจสอบหา User ที่โดนหลอกเอา Password บน เว็บเมล์

    วันก่อนได้รับจดหมายแจ้งเตือนว่า กำลังจะทำการปรับปรุงฐานข้อมูล email และจะทำการลบบัญชีที่ไม่ได้ใช้งาน เพื่อขยายพื้นที่ให้กับผู้ใช้รายใหม่ เพื่อเป็นการยืนยันว่าท่านยังมีการใช้งานอยู่โปรดกรอกข้อมูลตาม url ด้านล่าง มิเช่นนั้นบัญชีของท่านจะถูกลบ เมื่อคลิกเข้าไปดูตาม url ก็พบว่ามีช่องให้กรอกข้อมูล ชื่อผู้ใช้ และรหัสผ่าน แหมเจอแบบนี้ถ้าเป็นคนในวงการก็จะรู้ว่าหลอกลวงแน่นอน แต่ก็ยังมีผู้ใช้ที่รู้เท่าไม่ถึงการณ์หลงเชื่อ (จากประสบการณ์จะพบว่าผู้ใช้ทีหลงเชื่อโดยส่วนใหญ่จะเก่งภาษาอังกฤษหรือเป็นชาวต่างชาติครับ)

    Screenshot-1

    เมื่อลองตรวจดูที่ header ทั้งหมดของจดหมายดังกล่าวเพื่อหาว่าต้นตอของจดหมายถูกส่งมาจากที่ใด ก็พบว่าถูกส่งมาจาก 199.83.103.141 ซึ่งเมือตรวจสอบต่อไปก็พบว่าเป็น ip address ที่อยู่ในประเทศสหรัฐอเมริกา

    Screenshot-2

     ก็เลยชักสงสัยแล้วว่าผู้ใช้รายใดกันที่ส่งอีเมล์ฉบับนี้มากจากอเมริกา ก็เลยตรวจสอบจาก log ของเว็บเมล์เพื่อหาดูกิจกรรมของหมายเลข ip ดังกล่าว ก็พบว่า มีผู้ใช้รายหนึ่ง (จากรูปด้าล่างคื sophita.t) ได้ทำการ login โดยใช้ ip ดังกล่าวครับ ดังรูป

    Screenshot-3

    ตรวจสอบใน log ต่อไปก็พบว่า ip นี้มีการส่งจดหมายดังกล่าวจริง

    Screenshot-4

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

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

  • 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

  • แนวทางการ Backup บน Ubuntu Server (กรณีระบบ PSU EMail) #2

    ขยายความต่อจาก

    แนวทางการ Backup บน Ubuntu Server (กรณีระบบ PSU EMail)

    ลองมาดูทีละขั้นตอน

    1. ใน directory username.s มีไฟล์ดังนี้
    $ ls -l username.s
    total 0
    -rw-rw-r-- 1 mama mama 0 2013-04-29 14:31 a.txt
    -rw-rw-r-- 1 mama mama 0 2013-04-29 14:31 b.txt
    -rw-rw-r-- 1 mama mama 0 2013-04-29 14:31 c.txt
    -rw-rw-r-- 1 mama mama 0 2013-04-29 14:31 d.txt
    -rw-rw-r-- 1 mama mama 0 2013-04-29 14:31 e.txt

    2. ใช้คำสั่งต่อไปนี้ เพื่อทำการ Full Backup
    tar -zcf username.s-full.tar.gz -g username.s.snar username.s
    ดูไฟล์ใน username.s-full-tar.gz ด้วยคำสั่ง
    tar -ztf username.s-full.tar.gz -g username.s.snar username.s
    จะมีไฟล์ดังนี้
    username.s/
    username.s/a.txt
    username.s/b.txt
    username.s/c.txt
    username.s/d.txt
    username.s/e.txt

    3. ต่อมามีไฟล์เกิดใหม่ 2 ไฟล์ ชื่อ f.txt, g.txt
    4. เมื่อถึงเวลา ระบบทำการ Incremental Backup ด้วยคำสั่ง
    tar -zcf username.s-i01.tar.gz -g username.s.snar username.s
    ดูไฟล์ใน username.s-i01-tar.gz ด้วยคำสั่ง
    tar -ztf username.s-i01.tar.gz -g username.s.snar username.s
    จะมีไฟล์ดังนี้
    username.s/
    username.s/f.txt
    username.s/g.txt

    5. ลบไฟล์ c.txt, e.txt
    และมีไฟล์ h.txt เกิดขึ้น
    6. เมื่อถึงเวลา ระบบทำการ Incremental Backup ด้วยคำสั่ง
    tar -zcf username.s-i02.tar.gz -g username.s.snar username.s
    ดูไฟล์ใน username.s-i02-tar.gz ด้วยคำสั่ง
    tar -ztf username.s-i02.tar.gz -g username.s.snar username.s
    จะมีไฟล์ดังนี้
    username.s/
    username.s/h.txt

    7. (ในระบบ Email ไม่มีเหตุการณ์นี้ แต่ทำให้ดูเป็นตัวอย่าง) ถ้ามีการแก้ไขไฟล์ a.txt
    ซึ่งเดิมเป็นไฟล์ว่างๆ แต่ต่อมา มีการแก้ไขไฟล์ โดยเพิ่มคำว่า “hello world” เข้าไป
    echo "hello world" > username.s/a.txt
    8. เมื่อถึงเวลา ระบบทำการ Incremental Backup ด้วยคำสั่ง
    tar -zcf username.s-i03.tar.gz -g username.s.snar username.s
    ดูไฟล์ใน username.s-i03-tar.gz ด้วยคำสั่ง
    tar -ztf username.s-i03.tar.gz -g username.s.snar username.s
    จะมีไฟล์ดังนี้
    username.s/
    username.s/a.txt

    หวังว่าจะเป็นประโยชน์ครับ