Category: Open Source Software & Freeware

  • Oracle Database 12CR1 monitoring with MRTG

    • OS: Oracle Enterprise Linux  7.2  (CentOS 7.2)
    • วิธีติดตั้ง MRTG สามารถติดตั้งได้โดยสามารถดูคู่มือที่ ติดตั้ง mrtg บน ubuntu อาจไม่เหมือนกันแต่สามารถทำได้ทำนองเดียวกัน
    • กราฟสำหรับ Idle CPU and Load average, CPU Time spent waiting for IO, Traffic Analysis for eth0, TCP Current Establish สามารถใช้ script เดียวกับลิงค์ในข้อ ๒ ได้เลย
    • สร้างแฟ้ม /etc/mrtg/get-memory.sh มีข้อความว่า
      #!/bin/bash
      FREE=$(free |grep "Mem:"|awk '{print $7}')
      SWAP=$(free |grep "Swap:"|awk '{print $3}')
      TIME=$(uptime)
      echo "${FREE}"
      echo "${SWAP}"
      echo "$TIME"
      hostname 

      สร้างแฟ้ม /etc/mrtg/myhost-memory.cfg มีข้อความว่า
      WorkDir: /var/www/mrtg/myhost
      Target[myhost-mem]:`/etc/mrtg/get-memory.sh`
      MaxBytes[myhost-mem]: 20000000000
      Title[myhost-mem]: Free Memory and Swap Used
      PageTop[myhost-mem]: <H1>Free Memory and Swap Used</H1>
      ShortLegend[myhost-mem]: bytes
      YLegend[myhost-mem]: bytes
      LegendI[myhost-mem]:  Free Memory:
      LegendO[myhost-mem]: Swap Used:
      Legend1[myhost-mem]: Free memory, in bytes
      Legend2[myhost-mem]: Swap Used, in bytes
      Options[myhost-mem]: gauge, nopercent, growrightทดสอบสร้างภาพต้นแบบด้วยคำสั่ง

      env LANG=C /usr/bin/mrtg/myhost-memory.cfgปรับปรุงแฟ้ม index.html ด้วยคำสั่ง
      indexmaker --column=2 --output=/var/www/mrtg/myhost/index.html /etc/mrtg/myhost-cpu.cfg /etc/mrtg/myhost-cpu-io.cfg /etc/mrtg/myhost-speed-eth0.cfg /etc/mrtg/myhost-tcpestab.cfg /etc/mrtg/myhost-memory.cfg

    • โฟลเดอร์ที่ต้องเฝ้าระวังได้แก่ /u02/app/oracle/adump, /u02/app/oracle/diag/rdbms/regist/regist/alert, /u02/app/oracle/rdbms_trace ซึ่งเป็นโฟลเดอร์สำหรับเก็บ Log ไฟล์ต่างๆ ซึ่งอาจมีขนาดเพิ่มขึ้นจนระบบไม่สามารถให้บริการได้ และโฟลเดอร์ /u03 เป็นโฟลเดอร์ที่ใช้เก็บ archive log (ในกรณีที่ฐานข้อมูลเปิด archive log mode)
      • สร้างแฟ้ม /etc/mrtg/get-diskfree-misc1.sh มีข้อความว่า
        #!/bin/bash
        adump=$(du -sm /u02/app/oracle/adump|awk '{ print $1 }')
        free=$(df -m /u02|grep u02|awk '{ print $4 }')
        TEMP=$(uptime|grep -o "load average.*"|awk '{print $3}'|cut -d',' -f 1)
        LOAD=$(echo "${TEMP:-0} * 100"|bc|cut -d'.' -f 1)
        TIME=$(uptime)
        echo "${adump}"
        echo "${free}"
        echo "$TIME"
        hostname
      • สร้างแฟ้ม /etc/mrtg/myhost-diskfree-misc1.cfg มีข้อความว่า
        WorkDir: /var/www/mrtg/myhost
        Target[myhost-misc1]:`/etc/mrtg/get-diskfree-misc1.sh`
        MaxBytes[myhost-misc1]: 20000000000
        Title[myhost-misc1]: Free disk space and disk Used of /u02/app/oracle/adump
        PageTop[myhost-misc1]: Free disk space and disk Used of /u02/app/oracle/adump
        ShortLegend[myhost-misc1]: bytes
        kMG[myhost-misc1]: M,G,T
        kilo[myhost-misc1]: 1024
        YLegend[myhost-misc1]: bytes
        LegendI[myhost-misc1]: Disk Used:
        LegendO[myhost-misc1]: Free Disk:
        Legend1[myhost-misc1]: Disk usage, in Bytes
        Legend2[myhost-misc1]: Free Disk Space, in Bytes
        Options[myhost-misc1]: gauge, nopercent, growright
        Timezone[myhost-misc1]: Bangkok

        ทดสอบสร้างภาพต้นแบบด้วยคำสั่ง
        env LANG=C /usr/bin/mrtg /etc/mrtg/myhost-diskfree-misc1.cfg
        ปรับปรุงแฟ้ม index.html ด้วยคำสั่ง
        indexmaker --column=2 --output=/var/www/mrtg/myhost/index.html /etc/mrtg/myhost-cpu.cfg /etc/mrtg/myhost-cpu-io.cfg /etc/mrtg/myhost-speed-eth0.cfg /etc/mrtg/myhost-tcpestab.cfg /etc/mrtg/myhost-memory.cfg /etc/mrtg/myhost-diskfree-misc1.cfg
      • สร้างแฟ้มเลียนแบบข้อ 1 และ 2 สำหรับโฟลเดอร์ที่เหลือ
      • แก้ไขแฟ้ม /etc/mrtg/mymrtg.sh เพิ่มข้อความ  env LANG=C /usr/bin/mrtg /etc/mrtg/myhost-diskfree-misc1.cfg ต่อท้ายไฟล์และเพิ่มทุกไฟล์ของทุกโฟลเดอร์
      • สำหรับโฟลเดอร์ /u03 ให้สร้างแฟ้ม /etc/mrtg/get-diskfree-u03.sh มีข้อความว่า
        #!/bin/bash
        used=$(df -m /u03|grep u03|awk '{ print $3 }')
        free=$(df -m /u03|grep u03|awk '{ print $4 }')
        TEMP=$(uptime|grep -o "load average.*"|awk '{print $3}'|cut -d',' -f 1)
        LOAD=$(echo "${TEMP:-0} * 100"|bc|cut -d'.' -f 1)
        TIME=$(uptime)
        echo "${used}"
        echo "${free}"
        echo "$TIME"
        hostname
        nof=$(ls -d1 /u03/app/oracle/fast_recovery_area/REGIST/archivelog/* |wc -l)
        max=3if [ "${nof}" == "${max}" ]
        then
                nod=$(expr ${max} - 1)
                f2d=$(ls -d1 /u03/app/oracle/fast_recovery_area/REGIST/archivelog/*|head -${nod})
                rm -rf ${f2d}
                su - oracle -c "/bin/sh /home/oracle/reclaim.sh"
        fi
        สร้างแฟ้ม /home/oracle/reclaim.sh มีข้อความว่า
        rman target / <<EOF
        crosscheck archivelog all;
        delete noprompt expired archivelog all;
        quit
        EOF
        สร้างแฟ้ม /etc/mrtg/myhost-diskfree-u03.cfg มีข้อความว่า
        WorkDir: /var/www/mrtg/myhost
        Target[myhost-u03]:`/etc/mrtg/get-diskfree-u03.sh`
        MaxBytes[myhost-u03]: 20000000000
        Title[myhost-u03]: Free disk space and disk Used of /u03
        PageTop[myhost-u03]: Free disk space and disk Used of /u03
        ShortLegend[myhost-u03]: bytes
        kMG[myhost-u03]: M,G
        kilo[myhost-u03]: 1024
        YLegend[myhost-u03]: bytes
        LegendI[myhost-u03]: Disk Used:
        LegendO[myhost-u03]: Free Disk:
        Legend1[myhost-u03]: Disk usage, in Bytes
        Legend2[myhost-u03]: Free Disk Space, in Bytes
        Options[myhost-u03]: gauge, nopercent, growrightทดสอบสร้างภาพต้นแบบด้วยคำสั่ง
        env LANG=C /usr/bin/mrtg /etc/mrtg/myhost-diskfree-u03.cfg
        อย่าลืมปรับปรุงแฟ้ม index.html ด้วย
    • เฝ้าระวังขนาดของ Tablespace SYSTEM และ USERS
      • สร้างแฟ้ม /etc/mrtg/get-tablespace-system.sh มีข้อความว่า
        #!/bin/bash
        used=$(su - oracle -c "sh /home/oracle/monitor/tablespacesize.sh"|grep SYSTEM|awk '{ print $2 }'|sed -e 's/,//g')
        used=$(expr ${used} \* 1024)
        free=$(su - oracle -c "sh /home/oracle/monitor/tablespacesize.sh"|grep SYSTEM|awk '{ print $3 }'|sed -e 's/,//g')
        free=$(expr ${free} \* 1024)
        TIME=$(uptime)
        echo "${used}"
        echo "${free}"
        echo "$TIME"
        hostname

        สร้างแฟ้ม /home/oracle/monitor/tablespacesize.sh มีข้อความว่า
        #!/bin/bash
        sqlplus / as sysdba << EOF
        col "Tablespace" for a22
        col "Used MB" for 99,999,999
        col "Free MB" for 99,999,999
        col "Total MB" for 99,999,999
        select df.tablespace_name "Tablespace",
        totalusedspace "Used MB",
        (df.totalspace - tu.totalusedspace) "Free MB",
        df.totalspace "Total MB",
        round(100 * ( (df.totalspace - tu.totalusedspace)/ df.totalspace))
        "Pct. Free"
        from
        (select tablespace_name,
        round(sum(bytes) / 1048576) TotalSpace
        from dba_data_files
        group by tablespace_name) df,
        (select round(sum(bytes)/(1024*1024)) totalusedspace, tablespace_name
        from dba_segments
        group by tablespace_name) tu
        where df.tablespace_name = tu.tablespace_name ;
        quit
        EOF

        สร้างแฟ้ม /etc/mrtg/myhost-tablespace-system.cfg
        WorkDir: /var/www/mrtg/myhost
        Target[myhost-system]:`/etc/mrtg/get-tablespace-system.sh`
        MaxBytes[myhost-system]: 20000000000
        Title[myhost-system]: Tablespace SYSTEM disk usage
        PageTop[myhost-system]: Tablespace SYSTEM Disk Usage
        ShortLegend[myhost-system]: bytes
        kMG[myhost-system]: k,M,G
        kilo[myhost-system]: 1024
        YLegend[myhost-system]: bytes
        LegendI[myhost-system]: Disk Used:
        LegendO[myhost-system]: Free Disk:
        Legend1[myhost-system]: Disk usage, in Bytes
        Legend2[myhost-system]: Free Disk Space, in Bytes
        Options[myhost-system]: gauge, nopercent, growrightทดสอบสร้างภาพต้นแบบด้วยคำสั่ง
        env LANG=C /usr/bin/mrtg /etc/mrtg/myhost-tablespace-system.cfgอย่าลืมปรับปรุง index.html ด้วย
      • ทำแบบเดียวกันกับ tablespace users
    • จบขอให้สนุก
  • เล่าเรื่อง KM การใช้งานโอเพนซอร์สซอฟต์แวร์ ตอน การทำวิดีโอสื่อการสอนง่าย ๆ

    มีเพื่อน ๆ มาร่วมแลกเปลี่ยนเรียนรู้ ทั้งที่เป็น ผู้ดูแลระบบ และ อาจารย์ที่ให้ความสนใจ จำนวน 20 คน ผู้นำในการแลกเปลี่ยนฯในครั้งนี้คือ คุณคณกรณ์ หอศิริธรรม ศูนย์คอมพิวเตอร์ ม.อ. ได้นำความรู้จากการปฏิบัติจริงมาถ่ายทอดอย่างเป็นขั้นเป็นตอน

    เริ่มด้วยแนะนำการบันทึกวิดีโอด้วย Hangouts on Air ผู้เรียนทุกคนใช้ PSU GAFE (Google Apps For Education) account ซึ่งก็คือ PSU Email ที่ใช้อยู่และได้ผ่านขั้นตอน Password Setting (https://webmail.psu.ac.th/src/resetpassword.html) ในหน้าเว็บ https://webmail.psu.ac.th/src/login.php แล้ว แต่อาจใช้ gmail account ที่มีอยู่ก็ได้

    hangoutsonairโดยเริ่มต้นที่ไอคอนรูป Google+ เมื่อมีไฟล์ presentation พร้อม (เช่น Microsoft Powerpoint เป็นต้น) ก็ทำการ share เข้ามาใน hangouts on air ซึ่งเลือกได้ว่าจะแชร์ทั้งหน้าจอหรือเฉพาะ presentation ที่เตรียมไว้ แล้วทำการเริ่มบันทึกวิดีโอ เมื่อเสร็จก็ไปตัดต่อไฟล์บน youtube สนุกมาก ง่ายด้วย

    ถัดไปก็แนะนำ CamStudio Screen Recorder ให้เอาจาก http://sourceforge.net/projects/camstudio/ แต่ให้ระมัดระวังอย่าคลิกที่ปุ่มสีเขียว Download แต่ให้คลิก hyperlink ที่เขียนว่า Browse All Files ข้างใต้ ซึ่งจะเป็นไฟล์ติดตั้งที่ปลอดจาก Adware ครับ camstudio-iconCamStudio นี้ก็เอาไว้ใช้บันทึกหน้าจอที่เราจะบันทึกวิดีโอ ซึ่งเลือกได้เช่นกันว่าจะบันทึกเฉพาะบริเวณใด หรือ ทั้งหน้าจอ เมื่อทำการ Save จะได้ไฟล์ที่มีความคมชัดสูง ไฟล์ชนิด .avi ขนาดค่อนข้างใหญ่ อย่าบันทึกวิดีโอนานเกินไป

    เมื่อได้ไฟล์ชนิด .avi มาแล้ว เราก็นำไฟล์ไปผ่านกระบวนการตัดต่อด้วยโปรแกรม Windows Movie Maker ซึ่งติดตั้งจากที่นี่ Windows Movie Maker 2012 http://windows.microsoft.com/en-us/windows/get-movie-maker-download

    moviemaker-iconเมื่อตัดต่อ เพิ่มเสียงเพลง เพิ่มเสียงคำบรรยาย เพิ่มข้อความคำบรรยาย เพิ่มหน้านำ เพิ่มหน้าจบ เสร็จ ก็มีตัวเลือกให้อัปโหลด youtube ได้เลย

    greenshot-iconสุดท้าย เราก็ได้เรียนรู้โปรแกม Screen Capture ที่น่าใช้มากทีเดียว ชื่อ Greenshot – a free screenshot tool optimized for productivity http://getgreenshot.org/ ใช้งานแทน Snipping Tools ของ Windows ได้ดีกว่า และใช้งานแทน Snagit ที่ต้องจ่ายค่าใช้งานซอฟต์แวร์ได้

    โดยสรุปคือ เราสามารถทำการบันทึกเป็นวิดีโอได้ด้วยโปรแกรม Hangouts on Air จะได้ไฟล์เก็บอยู่ที่ youtube ทันทีแล้วค่อยดาวน์โหลดลงมาตัดต่อก็ได้ หรือ ตัดต่อด้วย Tools บน youtube ก็ได้ เราสามารถเลือกอีกโปรแกรมที่เป็น Client รันบน Windows คือ CamStudio แล้วนำไปตัดต่อด้วย Windows Movie Maker จนเสร็จ แล้วจึง upload ขึ้นบน youtube

  • สร้างเอกสาร PDF ด้วย iTextSharp

    ที่มา

    บ่อยครั้งที่ในชีวิตของโปรแกรมเมอร์จะต้องพบกับความต้องการของลูกค้าที่อยากได้รายงานหรือเอกสารที่สามารถสร้างได้จากระบบ แน่นอนว่าประเภทเอกสารที่ต้องการย่อมมี PDF บรรจุไว้แน่นอนเพราะเป็นเอกสารที่นิยมใช้กันอย่างแพร่หลาย ทั้งนี้ เครื่องมือสำหรับการสร้างเอกสารประเภทดังกล่าวมีอยู่มากมาย แต่จุดสำคัญนั้นอยู่ที่การเลือกใช้งานซึ่งย่อมแตกต่างกันไปตามปัจจัยต่าง ๆ เช่นในบทความนี้ ลูกค้าต้องการเอกสารเพื่อพิมพ์เป็น hard copy ไว้ที่หน่วยงาน ยังไม่ถึงขั้นรายงานนะครับ แค่เอกสารบันทึกข้อความ ดังนั้นผู้เขียนจึงไม่เลือกใช้เครื่องมือที่เก่งกาจเช่น Crystal report หรือ Reporting service และทำการค้นหาเครื่องมือที่มีน้ำหนักเบา (เวลาใช้ไม่กินทรัพยากรเยอะ) แต่ตอบสนองความต้องการได้ในขณะนั้น รวมไปถึงการมี documentation ที่ดี เข้าใจง่าย ปฏิบัติตามได้ไม่ยาก ซึ่งสุดท้ายก็มาเจอกับเครื่องมือที่ชื่อ iTextSharp

    คุณสมบัติของเครื่องมือ

    iTextSharp เป็นผลงานของ iText ซึ่งทำมาเพื่อการสร้างเอกสาร PDF บน C# platform โดยเฉพาะ ในขณะเดียวกันก็มีเครื่องมือแบบเดียวกันสำหรับ platform อื่น ๆ ด้วย เราจึงจะได้เห็นตัวอย่างใน documentation ของเขาเป็นภาษา Java

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

    การใช้งานเครื่องมือนี้จะต้องใช้การเขียนโปรแกรม 100% ครับหรือเรียกเป็นภาษาอังกฤษว่า Programmatically ซึ่งยุ่งยากพอควรทีเดียวโดยเฉพาะการจัดวางตำแหน่งของแต่ละส่วน พูดได้ว่าจะต้องจินตนาการหรือร่างแบบลงบนกระดาษเลยทีเดียว ทั้งนี้ทั้งนั้นนี่ก็เป็นข้อดีข้อหนึ่งสำหรับคนชอบเขียนโปรแกรมเพราะเห็นกระบวนการชัดเจน (ไม่ค่อยสะดวกแต่สนุกดี)

    ทดลองใช้

    ติดตั้งโปรแกรม

    ก่อนอื่นเลยก็ต้อง download library มาก่อนครับ (Link)การติดตั้งนั้นไม่ยาก แค่ reference ไปหา dll ที่เค้าให้มาก็พอ ไฟล์ที่ได้มามีทั้งหมด 3 ชุดครับคือ

    1. itextsharp-dll-core
    2. itextsharp-dll-pdfa
    3. itextsharp-dll-xtra

    ทั้งหมดนี้ทำหน้าที่แตกต่างกันครับ สำหรับการสร้าง PDF เราใช้แค่ตัว itextsharp-dll-core ก็พอ

    องค์ประกอบพื้นฐาน

    องค์ประกอบพื้นฐานของ itextsharp นั้นมีหลายตัว แต่ตัวที่เพียงพอสำหรับความต้องการของผู้เขียนในตอนนี้มีดังนี้ครับ

    1. Chunk เป็นองค์ประกอบสำหรับ “คำ”
    2. Phrase คือ “ประโยค” ซึ่งประกอบด้วยหลาย Chunk
    3. Paragraph คือ “ย่อหน้า” ซึ่งประกอบด้วยหลาย phrase และ chunk
    4. PdfPCell คือ cell ในตาราง
    5. PdfPTable คือ ตารางประกอบด้วยหลาย PdfPCell
    6. iTextSharp.text.Image คือรูปภาพ

    การกำหนด font และการเพิ่ม font

    iTextSharp นั้นสามารถเพิ่ม font ได้ครับ โดยการทำตามขั้นตอนดังนี้:

    BaseFont bf_bold = BaseFont.CreateFont(HttpContext.Current.Server.MapPath(“~/Regist/Theme/fonts/THSarabunNewBold.ttf”), BaseFont.IDENTITY_H, BaseFont.EMBEDDED);

    เท่านี้เราก็จะมี font แบบที่เราอยากได้ไว้ใช้งานในเอกสารครับ หลังจากนั้น เราก็สร้างตัวอักษรเพื่อใช้งาน ตามตัวอย่างนี้ครับ

    // Bold
    BaseFont bf_bold = BaseFont.CreateFont(HttpContext.Current.Server.MapPath(“~/Regist/Theme/fonts/THSarabunNewBold.ttf”), BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
    h1 = new Font(bf_bold, 18);
    bold = new Font(bf_bold, 16);
    smallBold = new Font(bf_bold, 14);

    // Normal
    BaseFont bf_normal = BaseFont.CreateFont(HttpContext.Current.Server.MapPath(“~/Regist/Theme/fonts/THSarabunNew.ttf”), BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
    normal = new Font(bf_normal, 16);
    smallNormal = new Font(bf_normal, 14);

    เริ่มต้นสร้างเอกสาร PDF

    เมื่อเรากำหนด font ไว้ใช้งานเสร็จแล้ว เราก็สามารถสร้างเอกสารได้เลยครับ  การสร้างเอกสารจะเริ่มจากการกำหนดขนาดเอกสารครับ ตามตัวอย่างนี้

     

    Document pdfDoc = new Document(PageSize.A4, 30, 30, 20, 20);
    PdfWriter pdfWriter = PdfWriter.GetInstance(pdfDoc, Response.OutputStream);
    pdfDoc.Open();

     

    โดยตัวเลข 4 ตัวหลัง layout ของกระดาษคือระยะขอบครับ

    เริ่มใส่องค์ประกอบลงในเอกสาร

    ตัวเอกสารของผมจะเริ่มจากส่วนที่เป็นหัวของเอกสารก่อน ซึ่งจะประกอบด้วยรูปภาพ 1 รูปและข้อความ 1 ข้อความ แต่ปัญหาอยู่การจัดการ layout เพราะเมื่อเราใส่องค์ประกอบเข้าไปมันจะชิดทางด้านซ้ายให้โดยอัตโนมัติ ในกรณีนี้จึงต้องใช้ PdfPTable มาช่วยจัดส่วนหัวเอกสารก่อนครับ ทำการกำหนดขนาดของตารางแล้วจัดองค์ประกอบเข้าไปอยู่ในแต่ละ cell

    private PdfPTable GetHeader() {

    PdfPTable headerTable = new PdfPTable(2);
    headerTable.TotalWidth = 530f;
    headerTable.HorizontalAlignment = 0;
    headerTable.SpacingAfter = 20;
    //headerTable.DefaultCell.Border = Rectangle.NO_BORDER;

    float[] headerTableColWidth = new float[2];
    headerTableColWidth[0] = 220f;
    headerTableColWidth[1] = 310f;

    headerTable.SetWidths(headerTableColWidth);
    headerTable.LockedWidth = true;

    iTextSharp.text.Image png = iTextSharp.text.Image.GetInstance(imagePath + “/thai_gov.png”);
    png.ScaleAbsolute(40, 40);

    PdfPCell headerTableCell_0 = new PdfPCell(png);
    headerTableCell_0.HorizontalAlignment = Element.ALIGN_LEFT;
    headerTableCell_0.Border = Rectangle.NO_BORDER;
    headerTable.AddCell(headerTableCell_0);

    PdfPCell headerTableCell_1 = new PdfPCell(new Phrase(“บันทึกข้อความ”, h1));
    headerTableCell_1.HorizontalAlignment = Element.ALIGN_LEFT;
    headerTableCell_1.VerticalAlignment = Element.ALIGN_BOTTOM;
    headerTableCell_1.Border = Rectangle.NO_BORDER;
    headerTable.AddCell(headerTableCell_1);

    return headerTable;
    }

    เมื่อทำการเพิ่มเข้าไปเอกสารแล้วจะได้ลักษณะตามภาพ

    pdf_header

    หลังจากนั้นผมก็เริ่มใส่องค์ประกอบที่เป็นรายละเอียดของส่วนหัวของเอกสารดังนี้

    private PdfPTable GetHeaderDetail() {
    PdfPTable table = new PdfPTable(2);
    table.TotalWidth = 530f;
    table.HorizontalAlignment = 0;
    table.SpacingAfter = 10;

    float[] tableWidths = new float[2];
    tableWidths[0] = 400f;
    tableWidths[1] = 130f;

    table.SetWidths(tableWidths);
    table.LockedWidth = true;

    Chunk blank = new Chunk(” “, normal);

    Phrase p = new Phrase();

    p.Add(new Chunk(“ส่วนราชการ”, bold));
    p.Add(new Chunk(blank));
    p.Add(new Chunk(“วิเทศสัมพันธ์”, normal));

    PdfPCell cell0 = new PdfPCell(p);
    cell0.Border = Rectangle.NO_BORDER;

    table.AddCell(cell0);

    p = new Phrase();
    p.Add(new Chunk(“โทร”, bold));
    p.Add(new Chunk(blank));
    p.Add(new Chunk(“2012”, normal));

    PdfPCell cell1 = new PdfPCell(p);
    cell1.Border = Rectangle.NO_BORDER;

    table.AddCell(cell1);

    p = new Phrase();
    p.Add(new Chunk(“ที่ มอ”, bold));
    p.Add(new Chunk(blank));
    p.Add(new Chunk(master.ApplicationNo, normal));

    cell0 = new PdfPCell(p);
    cell0.Border = Rectangle.NO_BORDER;

    table.AddCell(cell0);

    p = new Phrase();
    p.Add(new Chunk(“วันที่”, bold));
    p.Add(new Chunk(blank));
    p.Add(new Chunk(master.CreatedDate, normal));

    cell1 = new PdfPCell(p);
    cell1.Border = Rectangle.NO_BORDER;

    table.AddCell(cell1);

    p = new Phrase();
    p.Add(new Chunk(“เรื่อง”, bold));
    p.Add(new Chunk(blank));
    p.Add(new Chunk(“ขออนุมัติเดินทางไปต่างประเทศ”, normal));

    cell0 = new PdfPCell(p);
    cell0.Border = Rectangle.NO_BORDER;
    cell0.Colspan = 2;

    table.AddCell(cell0);

    return table;
    }

    เช่นเคยครับ เราจะต้องใช้ Table มากำหนด layout ของเอกสาร เมื่อทำการเพิ่มแล้วก็จะได้เอกสารหน้าตาดังนี้

    pdf_header_detail

    หลังจากนั้นก็ใส่องค์ประกอบต่าง ๆ เพิ่มเข้าไปทีละชิ้น ๆ ตาม source code ด้านล่าง

     

    private Paragraph GetBodyHeader()
    {
    Phrase p = new Phrase();

    p.Add(new Chunk(“เรียน “, normal));
    p.Add(new Chunk(“รองอธิการบดีฝ่ายองค์กรสัมพันธ์และสารสนเทศ”, normal));

    Paragraph para = new Paragraph(p);
    para.SpacingBefore = 20;
    para.SpacingAfter = 20;

    return para;
    }

    private Paragraph GetBody() {
    Paragraph para = new Paragraph();

    para.FirstLineIndent = 38.1f;

    para.Add(new Phrase(“ด้วย”, normal));
    para.Add(new Phrase(“งานวิเทศสัมพันธ์”, normal));
    para.Add(new Phrase(“ขออนุมัติให้นักศึกษาจำนวน ” + master.StudentCount + ” คน เดินทางไปราชการต่างประเทศระหว่างวันที่ ” + master.StartDate + ” ถึงวันที่ ” + master.EndDate + ” รวม ” + master.PeriodDay + ” วัน เพื่อดำเนินกิจกรรมดังต่อไปนี้”, normal));

    return para;
    }

    private PdfPTable GetActivities()
    {
    PdfPTable table = new PdfPTable(3);

    table.TotalWidth = 530f;
    table.HorizontalAlignment = 0;
    table.SpacingBefore = 20;
    table.SpacingAfter = 20;

    // ชื่อกิจกรรม
    // สถาบัน
    // ประเทศ

    float[] columnWidths = new float[3];
    columnWidths[0] = 200f;
    columnWidths[1] = 200f;
    columnWidths[2] = 130f;

    table.SetWidths(columnWidths);
    table.LockedWidth = true;

    PdfPCell cell0 = new PdfPCell(new Phrase(“กิจกรรม”, bold));
    cell0.HorizontalAlignment = Element.ALIGN_LEFT;
    cell0.Border = Rectangle.NO_BORDER;
    table.AddCell(cell0);

    PdfPCell cell1 = new PdfPCell(new Phrase(“สภานที่”, bold));
    cell1.HorizontalAlignment = Element.ALIGN_LEFT;
    cell1.Border = Rectangle.NO_BORDER;
    table.AddCell(cell1);

    PdfPCell cell2 = new PdfPCell(new Phrase(“ประเทศ”, bold));
    cell2.HorizontalAlignment = Element.ALIGN_LEFT;
    cell2.Border = Rectangle.NO_BORDER;
    table.AddCell(cell2);

    List<MasterActivity> activity = master.GetActivities();

    foreach (MasterActivity a in activity)
    {
    cell0 = new PdfPCell(new Phrase(a.ActivityNameThai, normal));
    cell0.HorizontalAlignment = Element.ALIGN_LEFT;
    cell0.Border = Rectangle.NO_BORDER;
    table.AddCell(cell0);

    cell1 = new PdfPCell(new Phrase(a.HostName, normal));
    cell1.HorizontalAlignment = Element.ALIGN_LEFT;
    cell1.Border = Rectangle.NO_BORDER;
    table.AddCell(cell1);

    Institution host = Institution.GetById(a.HostId);

    cell2 = new PdfPCell(new Phrase(host.CountryName, normal));
    cell2.HorizontalAlignment = Element.ALIGN_LEFT;
    cell2.Border = Rectangle.NO_BORDER;
    table.AddCell(cell2);
    }

    return table;
    }

    private Paragraph GetBodyFooter()
    {
    Paragraph para = new Paragraph(new Phrase(“จึงเรียนมาเพื่อโปรดพิจารณาอนุมัติด้วย จักเป็นพระคุณยิ่ง”, normal));
    para.FirstLineIndent = 38.1f;
    para.SpacingAfter = 25;
    return para;
    }

    private void GetSignature(Document pdfDoc) {

    Paragraph para;
    Phrase p;
    Chunk dotLine = new Chunk(“……………………………………………”, normal);

    //if (master.LevelId.Equals(“D”))
    //{
    // p = new Phrase(dotLine);
    // p.Add(new Chunk(“หัวหน้าภาควิชา”, normal));
    // para = new Paragraph(p);
    // pdfDoc.Add(para);
    //}

    p = new Phrase(dotLine);
    p.Add(new Chunk(“หัวหน้าภาควิชา”, normal));
    para = new Paragraph(p);
    para.SpacingAfter = 15;
    pdfDoc.Add(para);

    p = new Phrase(dotLine);
    p.Add(new Chunk(“คณบดี”, normal));
    para = new Paragraph(p);
    para.SpacingAfter = 15;
    pdfDoc.Add(para);
    }

     

    private PdfPTable GetStudentList() {

    Phrase p;

    PdfPTable table = new PdfPTable(8);
    table.TotalWidth = 530f;
    table.HorizontalAlignment = 0;
    //table.SpacingAfter = 20;
    //headerTable.DefaultCell.Border = Rectangle.NO_BORDER;

    float[] colWidths = new float[8];
    colWidths[0] = 30f;
    colWidths[1] = 70f;
    colWidths[2] = 70f;
    colWidths[3] = 70f;
    colWidths[4] = 70f;
    colWidths[5] = 70f;
    colWidths[6] = 70f;
    colWidths[7] = 70f;

    table.SetWidths(colWidths);
    table.LockedWidth = true;

    PdfPCell cell;

    p = new Phrase(“รายชื่อผู้เดินทางจาก ” + master.StartDate + ” ถึง ” + master.EndDate, normal);

    cell = new PdfPCell(p);
    cell.Colspan = 8;
    cell.HorizontalAlignment = Element.ALIGN_CENTER;
    cell.Border = Rectangle.NO_BORDER;
    cell.PaddingBottom = 10;
    table.AddCell(cell);

    #region Header

    cell = new PdfPCell(new Phrase(“ที่”, smallBold));
    cell.HorizontalAlignment = Element.ALIGN_CENTER;
    table.AddCell(cell);

    cell = new PdfPCell(new Phrase(“รหัสนักศึกษา”, smallBold));
    cell.HorizontalAlignment = Element.ALIGN_CENTER;
    table.AddCell(cell);

    cell = new PdfPCell(new Phrase(“คำนำหน้า”, smallBold));
    cell.HorizontalAlignment = Element.ALIGN_CENTER;
    table.AddCell(cell);

    cell = new PdfPCell(new Phrase(“ชื่อ”, smallBold));
    cell.HorizontalAlignment = Element.ALIGN_CENTER;
    table.AddCell(cell);

    cell = new PdfPCell(new Phrase(“สกุล”, smallBold));
    cell.HorizontalAlignment = Element.ALIGN_CENTER;
    table.AddCell(cell);

    cell = new PdfPCell(new Phrase(“คณะ”, smallBold));
    cell.HorizontalAlignment = Element.ALIGN_CENTER;
    table.AddCell(cell);

    cell = new PdfPCell(new Phrase(“วันที่เริ่ม”, smallBold));
    cell.HorizontalAlignment = Element.ALIGN_CENTER;
    table.AddCell(cell);

    cell = new PdfPCell(new Phrase(“วันที่สิ้นสุด”, smallBold));
    cell.HorizontalAlignment = Element.ALIGN_CENTER;
    table.AddCell(cell);

    #endregion

    #region Data

    List<OutboundApplication> apps = master.GetApplications();

    int i = 0;

    foreach (OutboundApplication app in apps)
    {
    cell = new PdfPCell(new Phrase((i + 1).ToString(), smallNormal));
    cell.HorizontalAlignment = Element.ALIGN_RIGHT;
    table.AddCell(cell);

    cell = new PdfPCell(new Phrase(app.StudentId, smallNormal));
    cell.HorizontalAlignment = Element.ALIGN_CENTER;
    table.AddCell(cell);

    cell = new PdfPCell(new Phrase(app.TitleName, smallNormal));
    cell.HorizontalAlignment = Element.ALIGN_LEFT;
    table.AddCell(cell);

    cell = new PdfPCell(new Phrase(app.Firstname, smallNormal));
    cell.HorizontalAlignment = Element.ALIGN_LEFT;
    table.AddCell(cell);

    cell = new PdfPCell(new Phrase(app.Lastname, smallNormal));
    cell.HorizontalAlignment = Element.ALIGN_LEFT;
    table.AddCell(cell);

    cell = new PdfPCell(new Phrase(app.FacultyNameThai, smallNormal));
    cell.HorizontalAlignment = Element.ALIGN_LEFT;
    table.AddCell(cell);

    cell = new PdfPCell(new Phrase(app.StartDate, smallNormal));
    cell.HorizontalAlignment = Element.ALIGN_CENTER;
    table.AddCell(cell);

    cell = new PdfPCell(new Phrase(app.EndDate, smallNormal));
    cell.HorizontalAlignment = Element.ALIGN_CENTER;
    table.AddCell(cell);

    i += 1;
    }

    #endregion

    return table;
    }

    และส่วนของ Main program ก็จะเป็นแบบนี้ครับ

    protected void Page_Load(object sender, EventArgs e)
    {
    InitElements();

    try
    {
    // Create PDF document
    Document pdfDoc = new Document(PageSize.A4, 30, 30, 20, 20);
    PdfWriter pdfWriter = PdfWriter.GetInstance(pdfDoc, Response.OutputStream);
    pdfDoc.Open();

    pdfDoc.Add(GetHeader());
    pdfDoc.Add(GetHeaderDetail());

    LineSeparator line = new LineSeparator();

    pdfDoc.Add(line);

    pdfDoc.Add(GetBodyHeader());
    pdfDoc.Add(GetBody());
    pdfDoc.Add(GetActivities());
    pdfDoc.Add(GetBodyFooter());
    GetSignature(pdfDoc);
    pdfDoc.NewPage();
    pdfDoc.Add(GetStudentList());

    pdfWriter.CloseStream = false;
    pdfDoc.Close();
    Response.Buffer = true;
    Response.ContentType = “application/pdf”;
    Response.AddHeader(“content-disposition”, “attachment;filename=Example.pdf”);
    Response.Cache.SetCacheability(HttpCacheability.NoCache);
    Response.Write(pdfDoc);
    Response.End();
    }
    catch (Exception ex)
    {
    Response.Write(ex.Message);
    }
    }

    สุดท้ายแล้วเราก็จะได้เอกสาร PDF หน้าตาแบบนี้ครับ Example

    บทสรุป

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

  • วิธีใช้งาน PSU Email ด้วยโปรแกรม Mozilla Thunderbird

    แสดงขั้นตอนการใช้ PSU Email ด้วยโปรแกรม Mozilla Thunderbird ทีละขั้นตอนตั้งแต่การดาวน์โหลดโปรแกรมรุ่นล่าสุดมาใช้ การตั้งค่าบัญชีผู้ใช้ การตั้งค่าการเชื่อมต่อกับเซิร์ฟเวอร์ และการตั้งค่าภาษาไทยที่ถูกต้อง

  • Dual Boot Ubuntu 14.04 & Windows 8.1 in UEFI

    • เหตุการณ์สมมติจึงใช้ VirtualBox
    • ตั้งค่า VirtualBox ดังภาพ (ขอข้ามวิธีการสร้างเครื่องใหม่บน VirtualBox ไปเลยนะครับ คิดซะว่าชำนาญแล้ว โดยขนาด HDD ที่ต้องการ 100GB เป็นอย่างน้อย) โดยเลือก option ที่เขียนว่า Enable EFI (special OSes Only) และในช่อง  Boot Order: ให้เลื่อนเป็น Optical แล้วตามด้วย Hard Disk แล้วกด OK
      uefi1
    • เมื่อเปิดเครื่องจะได้หน้าจอดังภาพ แสดงว่า BIOS ของเรากลายเป็น UEFI เรียบร้อยแล้ว
      uefi2
    • เลือกแผ่น Ubuntu 14.04 ให้ต่อเข้ากับ Device
      uefi3
    • reset เครื่อง
      uefi4
    • เลือก *Try Ubuntu without installing
      uefi5
    • รอจนได้ Windows Manager แล้วดับเบิ้ลคลิก Install Ubuntu 14.04.2 LTS บน Desktop เข้าสู่กระบวนการติดตั้ง Ubuntu ปกติทั่วไปสามารถใช้ Next Technology ได้เลยไปเรื่อยๆ จนถึงหน้า Installation type ให้เลือกหัวข้อ Something else แล้วกด Continue
      uefi6
    • คลิก New Partition Table… คลิก Continue จะได้ดังภาพ
      uefi7
    • คลิกคำว่า free space แล้วคลิกเครื่องหมายบวก (+) สร้าง Partition ขนาด 512MB มีชนิดเป็น EFI boot partition (ควรดูด้วยว่าพาทิชั่นที่ได้เมื่อสร้างเสร็จมีขนาด 512MB จริงๆ โดยใน VM ที่สร้างนี้ตอนสร้างใส่ไป 514MB) และกด + เพื่อสร้าง swap ในตัวอย่างกำหนดแรมไว้ 4GB สามารถสร้าง Swap เท่าแรมได้เลย และ / (root ขนาด 50GB) ตามลำดับโดยจะเหลือพื้นที่เปล่าไว้ด้วย
      uefi8
    • ภาพแสดงพาทิชั่นเมื่อสร้างเสร็จแล้ว
      uefi9
    • คลิก Install Now และคลิก Continue ที่เหลือหลังจากนี้สามารถกลับสู่โหมด Next Technology ได้เลยจนจบ
      uefi10
      uefi11
    • สิ้นสุดคลิก Restart Now
      uefi12
    • เอาแผ่นออกแล้วกด Enter (ปกติจะเอาออกให้อัตโนมัติ)
      uefi13
    • ลองบูตดูจนได้หน้า Log In
      uefi14
    • เลือก Devices แล้ว Optical Drives แล้วเลือกแผ่น Windows 8.1
      uefi15
    • คลิกรูปเฟืองที่มุมบนขวา เลือก Shutdown แล้วคลิก Restart
      uefi16
    • เมื่อ VM กำลัง Shutdown ให้สังเกตุดูว่า โลโก้ Ubuntu หายไปให้รีบ ESC ทันทีจะได้ดังภาพ
      uefi17
    • เลื่อน Cursor ลงมาที่ Boot Manager แล้วกด Enter จะได้ดังภาพ
      uefi18
    • เลื่อน Cursor ลงมาที่คำว่า EFI DVD/CDROM แล้วจะมีข้อความว่า Press any key to boot from CD or DVD….
      uefi19
    • เมื่อกดปุ่มใดๆ จะเข้าสู่วินโดวส์เพื่อเริ่มติดตั้ง
      uefi20
    • เมื่อได้หน้าเลือกภาษาให้เลือกดังภาพ แล้วคลิก Next
      uefi21
    • คลิก Install now
      uefi22
    • คลิกเครื่องหมายถูกหน้าข้อความ I accept the license terms คลิก Next
    • เลือก Custom: Install Windows only (advanced)
      uefi23
    • จะเห็นพื้นที่ดิสก์ที่เราใช้งานอยู่ในตอนนี้จะเห็นว่ามีที่เหลืออยู่ 48GB ที่เป็น Unallocated Space (และถูกเลือกโดยอัตโนมัติไว้อยู่แล้ว) ในตัวอย่างนี้เราจะสร้างเพียงไดรฟ์ซีเพียงอย่างเดียวให้คลิก Next
      uefi24
    • เข้าสู่การติดตั้ง Windows รอไปจนเสร็จ…
      uefi25
    • เมื่อติดตั้ง Windows  เสร็จแล้วจะถูกบังคับเข้าวินโดวส์ทันที Ubuntu หายไปแล้ว… เพราะ Boot Manager ของ Ubuntu ถูกเขียนทับไปนั่นเอง ให้ตั้งค่า Windows ให้เสร็จเรียบร้อยก่อนแล้วชัตดาวน์เครื่อง เลือก Devices แล้วเลือก Optical Drives เลือกแผ่น Ubuntu อีกครั้ง เมื่อได้ Menu ให้เลือก *Try Ubuntu without installing
      uefi26
    • เมื่อได้หน้า Windows Manager กด Ctrl+alt+T พิมพ์ข้อความดังนี้  และในขั้นตอนนี้ต้องแน่ใจว่าเครื่องเชื่อมต่อ Internet ได้เรียบร้อยแล้ว
      sudo add-apt-repository ppa:yannubuntu/boot-repair
      sudo apt-get update
      sudo apt-get install -y boot-repair
    • แล้วต่อด้วยคำสั่ง sudo boot-repair จะได้ดังภาพ
      uefi27
    • คลิกที่ Recommended repair จะได้ดังภาพ ให้รอไปจนเสร็จ
      uefi28
    • เมื่อได้หน้าจอดังภาพกด OK แล้วสั่งรีบูตได้เลยuefi29
    • เมื่อบูตขึ้นมาจะได้หน้าเมนูที่คุ้นเคยสามารถเลือกได้ว่าจะเข้าอะไร
      uefi30
    • จบขอให้สนุกครับ

    อ้างอิงเพิ่มเติม

    https://help.ubuntu.com/community/Boot-Repair

  • How to reset root password CentOS 7.1

    • เข้า Single user mode โดย reboot แล้วเมื่อได้เมนูของ Grub ให้เลื่อนแถบสีไปยัง Kernel ที่ต้องการบูต (โดยปกติจะถูกเลือกไว้อยู่แล้ว) ให้กด e
      reset1จะได้หน้าจอดังนี้
      reset2สิ่งที่เราสนใจคือบรรทัดที่ขึ้นต้นว่า linux ซึ่งในบทความนี้คือ linux16 สำหรับ CentOS 7/7.1 x86_64 บนเมนบอร์ดที่ใช้ระบบ BIOS (อาจจะพบกับ linuxefi สำหรับเมนบอร์ดที่ใช้ระบบ UEFI) เมื่อหาเจอแล้วเลื่อน cursor ไปที่ ข้อความ ro
      reset2-1เปลี่ยน ro เป็น rw init=/sysroot/bin/sh
      reset3-1กดปุ่ม ctrl และปุ่ม x พร้อมกันเพื่อบูตระบบจะได้ดังภาพ
      reset4
    • พิมพ์คำสั่ง chroot  /sysroot
      reset5-1
    • พิมพ์ passwd เพื่อเปลี่ยนรหัสผ่านสำหรับ root
    • สร้างแฟ้ม autorelabel เพื่อปรับปรุงกฏของ selinux (ถึงแม้จะไม่ได้ใช้งาน selinux ก็ตาม เพื่อความไม่ประมาท) โดยคำสั่ง touch /.autorelabel
    • พิมพ์ exit เพื่อยกเลิก chroot
    • พิมพ์ reboot
      reset6-1
    • ระบบจะรีบูตสองรอบ อัตโนมัติเพื่อปรับปรุง selinux และไฟล์ autorelabel จะถูกลบอัตโนมัติ
    • ล็อคอินเข้าระบบด้วยผู้ใช้ root และ password ที่เปลี่ยนไป ลบแฟ้ม /.bash_history ทิ้งด้วยคำสั่ง rm /.bash_history (ถูกสร้างตอนออกจากระบบ chroot)
    • จบขอให้สนุกครับ

    อ้างอิงเพิ่มเติม
    https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/7/html/System_Administrators_Guide/sec-Terminal_Menu_Editing_During_Boot.html#sec-Recovering_Root_Password

  • How to restore a system after accidentally removing all kernels?

    เหตุการณ์สมมติ… ทำไงดี??? เผลอรันคำสั่ง

    sudo apt-get remove --purge linux-image-3.19.0-*

    ได้ผลดังรูป (ดันกด y แล้ว enter อีกนะ)
    Capture1งานงอก …ลอง ls /boot เผื่อว่ายังมี Kernel เหลืออยู่บ้าง
    Capture2
    คุณพระ ไปหมดแล้ว… ตกใจ!!! reboot สิ… (กรั่ก ๆ)
    (หากไม่ตกใจจน reboot ไปซะก่อนสามารถพิมพ์คำสั่ง sudo apt-get install linux-image-generic ได้เลย)
    Capture3 เงิบ!!! เหลือแต่ Memory Test….

    แก้ไขโดยหาแผ่น Ubuntu Desktop ควรเป็นรุ่นเดียวกับรุ่นที่ติดตั้ง 12.04, 14.04 เป็นต้น (แต่แนะนำ 14.04 ถึงแม้จะกู้เครื่องที่เป็น 12.04)

    • เมื่อบูตให้เลือก Try Ubuntu รอจน Desktop ขึ้นมาเรียบร้อย เปิด Terminal ขึ้นมา (กด ctrl+alt+t)
    • พิมพ์คำสั่ง sudo fdisk /dev/sda -l (กรณีนี้รู้แน่ๆ ว่าติดตั้งบน /dev/sda)
      Capture4
    • จากรูปมีสอง patition ที่น่าจะติดตั้ง Ubuntu เอาไว้ คือ /dev/sda1 และ /dev/sda5 ถ้าใช้แผ่น 12.04 จะไม่สามารถ mount ส่วนของ /dev/sda5 ได้เพราะมองไม่เห็น patition ที่เป็น LVM ตั้งแต่แรก แต่แผ่น 14.04 มองเห็น
      Capture5
    • เมื่อคลิกที่ 103 GB Volume สามารถมองเห็นไฟล์ทั้งหมด
      Capture6
    • ลองเปิดไฟล์ใน etc/fstab ดูไฟล์ข้างในว่า partition อยู่อย่างไร
      Capture7
    • พบว่า /dev/sda1 เป็น boot และ /dev/mapper/ubuntu–vg-root เป็น / และ /dev/mapper/ubuntu–vg-swap_1 เป็น swap เราสนใจแค่ boot และ /
    • สั่ง mount patition ตามลำดับต่อไปนี้
      sudo mount /dev/mapper/ubuntu--vg-root /mnt
      sudo mount /dev/sda1 /mnt/boot
      sudo mount --bind /dev /mnt/dev
      sudo mount --bind /sys /mnt/sys
      sudo mount --bind /proc /mnt/proc
      Capture1111
    • สั่งคำ chroot ไปยัง /mnt สังเกตว่าหลังจากสั่งคำสั่ง chroot แล้ว prompt จะเปลี่ยนเป็น root@ubuntu:/#
      sudo chroot /mnt
      Capture9
    • ให้ตรวจสอบแฟ้ม /etc/apt/sources.list ว่าใช้ repository ไหนด้วย หากไม่ได้ใช้ th.archive.ubuntu.com หรือ mirror.psu.ac.th หรือ mirrors.psu.ac.th หรือ mirror1.ku.ac.th ให้เปลี่ยนเป็น th.archive.ubuntu.com จากนั้นทดสอบ nslookup th.archive.ubuntu.com สำหรับคนที่ resolve ได้ (เรายินดีด้วย) ข้ามข้อ ๑๐ ไปได้เลย
      Capture11
    • แก้ไขแฟ้ม /etc/hosts
      สำหรับเครื่องที่อยู่นอกมหาวิทยาลัยเพิ่มข้อความว่า
      192.100.77.186 th.archive.ubuntu.com
      สำหรับเครื่องที่อยู่ภายในมหาวิทยาลัยเพิ่มข้อความว่า
      192.168.101.34 th.archive.ubuntu.com
       
    • สั่ง
      apt  install linux-image-generic
      Capture1112
    • รอจนเสร็จได้ข้อความสุดท้ายประมาณว่า  Setting up linux-image-generic (… ให้แก้ไขไฟล์ /etc/hosts โดยเอาบรรทัดที่เพิ่มเข้าไปออก
    • พิมพ์คำสั่งต่อไปนี้ตามลำดับ
      exit
      sudo umount /mnt/proc /mnt/dev /mnt/sys /mnt/boot /mnt
      sudo reboot
    • เย่บูตได้..
    • จบขอให้สนุกครับ
  • iTALC 2.0.2 โปรแกรมควบคุมคอมพิวเตอร์ในห้องเรียน

    italc-installation-2-window
    มาแนะนำกันอีกสักรอบสำหรับ iTALC 2.0.2 โปรแกรมควบคุมคอมพิวเตอร์ในห้องเรียน เป็นซอฟต์แวร์ชนิดโอเพนซอร์สที่บางคนก็ได้ลองใช้ในเวอร์ชั่นแรก ๆ ไปบ้างแล้ว ผมลองเข้าไปดูในเว็บไซต์ผู้สร้างโปรแกรมก็เห็นว่ายังคงอัปเดตปรับปรุงโปรแกรมกันอยู่ถึงปัจจุบัน ก็เลยสนใจลองทดสอบดูครับ

    iTALC ทำอะไรได้หลายอย่าง เช่น ผู้สอนสามารถ Lock หน้าจอเครื่องผู้เรียน สามารถส่งภาพหน้าจอเครื่องผู้สอนไปยังหน้าจอเครื่องผู้เรียนได้ สามารถรีโมทคอนโทรลเข้าไปเครื่องผู้เรียนได้ สั่งปิดเครื่องทุกเครื่องได้ หรือ สั่งเปิดเครื่องได้หาก BIOS พร้อมใช้งาน

    ดาวน์โหลดโปรแกรมได้ที่ http://italc.sourceforge.net/
    italc-installation-1-file

    ติดตั้งเสร็จจะได้ไอคอนที่หน้า Desktop ดังรูป
    italc-installed-desktop-window
    และไอคอนที่หน้า Apps ดังรูป
    italc-installed-apps-window
    โปรแกรม iTALC Management Console
    italc-management-4-export-key-1-window
    เครื่องผู้สอน จะเรียกว่า master computer ในขั้นตอนการติดตั้งโปรแกรมที่เครื่องผู้สอน ให้เลือก component iTALC service และ iTALC master และให้เลือก Create new access keys
    italc-installation-3-choose-window
    เครื่องผู้เรียน จะเรียกว่า client computer ในขั้นตอนการติดตั้งโปรแกรมที่เครื่องผู้เรียน ให้เลือก component iTALC service แต่ไม่เลือก iTALC master และให้เลือก Import public key
    italc-management-4-export-key-2-window

    วิธีที่จะทำให้เครื่องผู้สอนควบคุมเครื่องผู้เรียนได้ก็คือการ export public key ซึ่งจะได้ไฟล์ชื่อ italc_public_key.key.txt ด้วยโปรแกรม iTALC Management Console นั้นเช่นกัน
    italc-management-4-export-key-4-window
    แล้วนำไปใส่เข้าในเครื่องผู้เรียนด้วยโปรแกรมเดียวกัน
    italc-management-import-key-3-window
    เมื่อทำขั้นตอนติดตั้งเสร็จแล้ว ก็เป็นการตั้ง classroom ว่าชื่ออะไร และมีคอมพิวเตอร์ใดบ้าง (IP) อยู่ใน classroom นี้ แล้วก็ใช้งานซึ่งการใช้งานง่ายมากเลย
    italc-setting-classroom-finished

    ผมเขียนวิธีการสำหรับ Windows 8.1 ที่นี่ครับ
    http://opensource.cc.psu.ac.th/โปรแกรมควบคุมคอมพิวเตอร์ในห้องเรียน

    และวิธีการสำหรับ Linux Mint 17.1 ที่นี่ครับ
    http://opensource.cc.psu.ac.th/ติดตั้ง_iTALC_บน_Linux_Mint

    คำถามยอดฮิตคือ แล้วมันใช้ควบคุมได้กี่เครื่อง อันนี้ผมยังไม่ได้ทดสอบครับ ฮ่า ฮ่า รอท่านทดสอบแล้วบอกผมด้วยนะครับ

    หวังว่าคงจะมีประโยชน์ อย่างน้อยที่สุดเอามาใช้ควบคุมเครื่องที่อยู่ในความดูแลไม่กี่เครื่องก็ใช้ได้นะ

  • Dialog cannot open tty-output

    dialog บน Oracle Enterprise Linux และ Ubuntu ไม่เหมือนกัน (ทำไมล่ะ…ไม่ทราบครับ)

    สร้างสคริปต์ชื่อ file.sh มีข้อความว่า

    #!/bin/bash
    FILE=$(dialog --ascii-lines --title "Delete a file" --stdout \
    --title "Please choose a file to delete" --fselect /tmp/ 14 48)
    echo $FILE

    บน Ubuntu รันได้ผลลัพธ์
    Ubuntu's Dialogแต่บน Oracle Enterprise Linux
    Oracle Enterprise LInux' Dialog-_-

    ต้องเปลี่ยนสคริปต์มีสองแบบ
    แบบแรก
    #!/bin/sh
    dialog --ascii-lines --title "Delete a file" --stdout \
    --title "Please choose a file to delete" --fselect /tmp/ 14 48 2>/tmp/file.tmp
    echo $(cat /tmp/file.tmp)

    แบบที่สอง
    #!/bin/bash
    FILE=$(dialog --ascii-lines --title "Delete a file" --stdout \
    --title "Please choose a file to delete" --fselect /tmp/ 14 48 2>&1>/dev/tty)
    echo $FILE

    ผลลัพธ์ของทั้งสองแบบให้ผลเหมือนกันคือ
    Oracle Enterprise Linux's Dialog2จบ..วันนี้ห้วนไปหน่อย ขอให้สนุกครับ