VS Code font rendering looks ugly on Linux

source : https://github.com/Microsoft/vscode/issues/35675

  1. Create fontconfig.conf and put this file in /usr/share/code/fontconfig.conf
    <?xml version='1.0'?>
    <!DOCTYPE fontconfig SYSTEM 'fonts.dtd'>
    <fontconfig>
      <!-- Force RGBA subpixel aliasing to «none» in code and code-insiders -->
      <match target="pattern">
        <or>
          <test name="prgname">
            <string>code</string>
          </test>
          <test name="prgname">
            <string>code-insiders</string>
          </test>
        </or>
        <edit name="rgba" mode="assign">
          <const>none</const>
        </edit>
      </match>
    </fontconfig>
  2. Symlink file to /etc/fonts/conf.d/99-vscode.conf

Dynamic pivoting in MySQL

คิดถึงรายงานคิดถึง Excel 555 … เรื่องความตั้งใจในการเรียน Microsoft Excel นี่มีมาสักพักแล้ว เริ่มด้วยการซื้อหนังสือมาก่อนแต่น่าจะหลายเดือนละ (จนลืมไปเลยว่าซื้อมาตอนไหน บาปมาก) แต่ก็นะความขี้เกียจครอบงำ ช่วงนี้ก็เลยเป็นช่วงอ่านหนังสือ Microsoft Excel แบบจริงจัง (แอบตั้งใจ)
เปิดดูคร่าว ๆ มีบทนึงพูดถึงเรื่องการทำ Pivot Table ในโปรแกรมตระกูลตารางคำนวณเรื่องนี้ทุกตัวในตลาดก็สามารถทำได้ ถือเป็นหนึ่งใน Killer Feature แต่เรื่องนี้แค่ประเด็นนิดหน่อย ^_^

สำหรับคนที่เขียนคำสั่งเรียกดูข้อมูล (SQL) ก็ทำเรื่องนี้อยู่เนือง ๆ หลายครั้งก็ทำแบบฮาร์ดคอร์ ณ ตอนนั้นเลย ตัวอย่างคร่าว ๆ สมมุติเรามีข้อมูลค่าใช้จ่ายภายในบ้านสรุปประมาณนี้ ในฐานข้อมูล (ด้านซ้าย) และต้องการแสดงผลเป็นอีกรูปด้านขวา

SQL แสดงรายงานแบบนี้ อนุมานจากข้อมูลดิบที่เก็บในฐานข้อมูล ก่อนที่เราจะสรุปได้ก็น่าจะมีประมาณนี้ (เราใช้บริการของ generatedata.com) เอาตัวอย่างข้อมูลสัก 100 รายการหล่ะกัน

DROP TABLE IF EXISTS `ExpenseCategory`;
CREATE TABLE `ExpenseCategory` (
  `CategoryId` varchar(255) NOT NULL,
  `CategoryName` varchar(255) default NULL,
  PRIMARY KEY (`CategoryId`)
);

INSERT INTO `ExpenseCategory` (`CategoryId`,`CategoryName`) VALUES ("01","ความบันเทิง"),("02","ของชำ"),("03","ครอบครัว"),("04","การคมนาคมขนส่ง");

DROP TABLE IF EXISTS `Expense`;
CREATE TABLE `Expense` (
  `id` mediumint(8) unsigned NOT NULL auto_increment,
  `CategoryId` varchar(255) default NULL,
  `ExpenseDate` varchar(255),
  `Amount` varchar(100) default NULL,
  PRIMARY KEY (`id`)
) AUTO_INCREMENT=1;

INSERT INTO `Expense` VALUES (1,'04','2018-07-19 02:55:09','83369'),(2,'01','2018-01-17 19:18:21','28001'),(3,'04','2018-06-29 03:32:27','17058'),(4,'04','2018-07-04 17:44:03','64619'),(5,'04','2018-07-22 17:38:56','24050'),(6,'04','2018-08-15 03:43:50','80585'),(7,'03','2018-06-11 23:52:59','79427'),(8,'02','2018-04-29 04:03:38','63177'),(9,'01','2018-09-03 04:02:46','77975'),(10,'04','2018-07-04 21:49:15','61752'),(11,'01','2018-02-21 11:39:34','59245'),(12,'04','2018-01-05 05:42:14','15695'),(13,'02','2018-09-13 09:07:51','22132'),(14,'02','2018-08-12 13:24:09','58156'),(15,'01','2018-08-14 18:34:16','7802'),(16,'01','2018-04-04 04:26:02','44733'),(17,'03','2018-11-03 02:59:01','73158'),(18,'04','2018-01-23 09:59:45','69724'),(19,'02','2018-11-16 07:39:50','98963'),(20,'03','2018-01-04 11:20:59','93659'),(21,'02','2018-08-25 22:01:10','13945'),(22,'04','2018-04-08 22:46:07','90735'),(23,'01','2018-09-13 10:20:59','76856'),(24,'01','2018-09-02 08:45:17','54668'),(25,'03','2018-12-06 12:19:30','45571'),(26,'02','2018-05-27 09:48:40','24694'),(27,'01','2018-04-15 03:01:29','73961'),(28,'01','2018-03-11 06:05:34','53546'),(29,'02','2018-12-27 06:57:17','91375'),(30,'04','2018-02-05 05:14:19','44997'),(31,'02','2018-12-15 02:35:52','54144'),(32,'02','2018-08-01 02:06:37','95898'),(33,'02','2018-02-18 08:50:43','79249'),(34,'02','2018-03-26 04:39:35','66184'),(35,'01','2018-07-26 13:17:03','44670'),(36,'02','2018-12-26 13:50:39','88500'),(37,'04','2018-04-19 20:26:25','31414'),(38,'01','2018-07-28 13:53:24','56802'),(39,'02','2018-04-27 06:18:15','67682'),(40,'01','2018-10-11 12:25:37','98233'),(41,'03','2018-09-28 12:36:05','43118'),(42,'02','2018-08-17 16:06:34','94942'),(43,'02','2018-12-16 16:28:16','25039'),(44,'04','2018-04-14 15:47:06','87368'),(45,'03','2018-11-21 16:53:01','49355'),(46,'04','2018-01-06 17:08:54','63354'),(47,'03','2018-02-02 11:06:33','26540'),(48,'01','2018-10-19 03:50:49','32534'),(49,'01','2018-05-15 23:40:11','58038'),(50,'03','2018-04-28 23:53:24','2915'),(51,'01','2018-03-30 18:57:12','10229'),(52,'03','2018-04-22 07:47:45','20004'),(53,'03','2018-08-16 23:42:08','69185'),(54,'02','2018-03-09 20:38:52','92533'),(55,'02','2018-12-25 23:51:10','66589'),(56,'04','2018-09-22 05:40:21','94759'),(57,'01','2018-06-03 13:24:32','76588'),(58,'03','2018-04-21 07:27:01','66573'),(59,'02','2018-09-25 03:49:02','76607'),(60,'01','2018-08-11 10:48:24','47755'),(61,'04','2018-11-02 02:37:54','69570'),(62,'02','2018-08-31 14:44:15','25560'),(63,'02','2018-03-23 07:24:59','78550'),(64,'04','2018-06-07 17:39:12','18455'),(65,'02','2018-10-31 11:14:30','71227'),(66,'01','2018-10-31 14:23:16','2454'),(67,'04','2018-08-14 21:16:17','54700'),(68,'04','2018-06-05 01:04:59','59554'),(69,'01','2018-01-23 10:33:50','37798'),(70,'04','2018-06-09 12:00:56','59983'),(71,'04','2018-02-19 15:56:33','56754'),(72,'04','2018-12-24 13:14:33','54684'),(73,'02','2018-05-15 23:08:16','66531'),(74,'02','2018-06-25 19:08:32','25407'),(75,'02','2018-11-25 18:53:14','96119'),(76,'01','2018-05-28 02:43:26','30991'),(77,'04','2018-03-18 02:03:29','81845'),(78,'02','2018-02-18 20:23:03','1057'),(79,'01','2018-11-15 16:32:26','52151'),(80,'01','2018-07-25 19:54:37','91069'),(81,'04','2018-04-18 14:02:13','51134'),(82,'02','2018-06-04 07:27:50','4609'),(83,'04','2018-07-07 20:22:38','62669'),(84,'02','2018-08-13 10:40:36','93161'),(85,'03','2018-03-29 12:51:47','75717'),(86,'04','2018-04-03 15:35:12','67327'),(87,'04','2018-02-06 15:56:58','87785'),(88,'01','2018-12-16 04:38:52','34503'),(89,'03','2018-07-25 02:52:09','87144'),(90,'04','2018-08-21 21:48:58','37756'),(91,'01','2018-07-25 20:38:00','5070'),(92,'01','2018-05-23 17:56:31','40138'),(93,'01','2018-01-10 22:47:36','35626'),(94,'01','2018-03-20 22:01:19','94446'),(95,'01','2018-05-20 23:55:32','65411'),(96,'02','2018-08-06 07:52:03','48145'),(97,'02','2018-05-26 22:38:07','17564'),(98,'01','2018-05-31 21:40:52','59694'),(99,'03','2018-03-03 16:47:55','18672'),(100,'01','2018-04-29 06:15:51','52622');

ปกติ(เรา)เขียน SQL เพื่อสรุปค่าใช้จ่ายแยกตามประเภทและรายเดือนตามตารางรูปขวา

SELECT
    CategoryName, 
    SUM(IF(M = 1, TotalAmount, 0 )) AS '1',
    SUM(IF(M = 2, TotalAmount, 0 )) AS '2',
    SUM(IF(M = 3, TotalAmount, 0 )) AS '3',
    SUM(IF(M = 4, TotalAmount, 0 )) AS '4',
    SUM(IF(M = 5, TotalAmount, 0 )) AS '5',
    SUM(IF(M = 6, TotalAmount, 0 )) AS '6',
    SUM(IF(M = 7, TotalAmount, 0 )) AS '7',
    SUM(IF(M = 8, TotalAmount, 0 )) AS '8',
    SUM(IF(M = 9, TotalAmount, 0 )) AS '9',
    SUM(IF(M = 10, TotalAmount, 0 )) AS '10',
    SUM(IF(M = 11, TotalAmount, 0 )) AS '11',
    SUM(IF(M = 12, TotalAmount, 0 )) AS '12',
    SUM(TotalAmount) AS Total
FROM (
    SELECT
        MONTH(Expense.ExpenseDate) AS M,
        MONTHNAME(Expense.ExpenseDate) AS MN,
        Expense.CategoryId, 
        ExpenseCategory.CategoryName, 
        SUM(Amount) AS TotalAmount
    FROM Expense INNER JOIN ExpenseCategory ON Expense.CategoryId = ExpenseCategory.CategoryId
    GROUP BY Expense.CategoryId, MONTH(Expense.ExpenseDate)
) T 
GROUP BY T.CategoryId 
ORDER BY T.CategoryId ASC;

ผลลัพธ์ก็จะประมาณนี้

  • แถวเป็นประเภทค่าใช้จ่าย
  • คอลัมภ์เป็นยอดรวมรายเดือน

แบบนี้บ่อย ๆ ก็เหนื่อยเหมือนกันนะ  (อาจมีคนเขียน SQL สั้นและง่ายกว่านี้แหล่ะ  ก็ช่วยแนะนำด้วยหล่ะกันครับ) มันต้องมีคนเคยเหนื่อยเหมือนเรานะ และก็มีจริงด้วย คุณ Rick James เค้าก็ทำ Function เพื่อทำ Pivot Table ไว้เหมือนกัน (Blog นี้แนะนำให้อ่านเลย)

DELIMITER //
DROP   PROCEDURE IF EXISTS PIVOTTABLE //
CREATE PROCEDURE PIVOTTABLE(
    IN tbl_name VARCHAR(99),       -- table name (or db.tbl)
    IN base_cols VARCHAR(99),      -- column(s) on the left, separated by commas
    IN pivot_col VARCHAR(64),      -- name of column to put across the top
    IN tally_col VARCHAR(64),      -- name of column to SUM up
    IN where_clause VARCHAR(99),   -- empty string or "WHERE ..."
    IN order_by VARCHAR(99)        -- empty string or "ORDER BY ..."; usually the base_cols
    )
    DETERMINISTIC
    SQL SECURITY INVOKER
BEGIN
    -- Find the distinct values
    -- Build the SUM()s
    SET @subq = CONCAT('SELECT DISTINCT ', pivot_col, ' AS val ',
                    ' FROM ', tbl_name, ' ', where_clause, ' ORDER BY 1');
    -- select @subq;

    SET @cc1 = "CONCAT('SUM(IF(&p = ', &v, ', &t, 0)) AS ', &v)";
    SET @cc2 = REPLACE(@cc1, '&p', pivot_col);
    SET @cc3 = REPLACE(@cc2, '&t', tally_col);
    -- select @cc2, @cc3;
    SET @qval = CONCAT("'\"', val, '\"'");
    -- select @qval;
    SET @cc4 = REPLACE(@cc3, '&v', @qval);
    -- select @cc4;

    SET SESSION group_concat_max_len = 10000;   -- just in case
    SET @stmt = CONCAT(
            'SELECT  GROUP_CONCAT(', @cc4, ' SEPARATOR ",\n")  INTO @sums',
            ' FROM ( ', @subq, ' ) AS top');
     select @stmt;
    PREPARE _sql FROM @stmt;
    EXECUTE _sql;                      -- Intermediate step: build SQL for columns
    DEALLOCATE PREPARE _sql;
    -- Construct the query and perform it
    SET @stmt2 = CONCAT(
            'SELECT ',
                base_cols, ',\n',
                @sums,
                ',\n SUM(', tally_col, ') AS Total'
            '\n FROM ', tbl_name, ' ',
            where_clause,
            ' GROUP BY ', base_cols,
            '\n WITH ROLLUP',
            '\n', order_by
        );
    select @stmt2;                    -- The statement that generates the result
    PREPARE _sql FROM @stmt2;
    EXECUTE _sql;                     -- The resulting pivot table ouput
    DEALLOCATE PREPARE _sql;
    -- For debugging / tweaking, SELECT the various @variables after CALLing.
END;
//
DELIMITER ;

วิธีเรียกใช้งานก็ง่าย ๆ เลยแบบนี้

CALL PIVOTTABLE('TEMP', 'CategoryName', 'M', 'TotalAmount', '', ' ORDER BY CategoryId');

ตาราง TEMP ก็สร้างขึ้นมาจากสรุป (ตารางฝั่งซ้ายจากรูปแรก)

DROP TABLE IF EXISTS TEMP;
CREATE TABLE TEMP (
    SELECT
        MONTH(Expense.ExpenseDate) AS M,
        MONTHNAME(Expense.ExpenseDate) AS MN,
        Expense.CategoryId AS CategoryId, 
        ExpenseCategory.CategoryName AS CategoryName, 
        SUM(Amount) AS TotalAmount
    FROM Expense INNER JOIN ExpenseCategory ON Expense.CategoryId = ExpenseCategory.CategoryId
    GROUP BY Expense.CategoryId, MONTH(Expense.ExpenseDate)
);

SELECT * FROM TEMP;

หลังจากเรียกฟังก์ชั่นเสร็จผลลัพธ์ก็เหมือนที่เราเขียนเองนั่นแหล่ะ ^_^ แต่ลดแรงงานได้อีก

CALL PIVOTTABLE('TEMP', 'CategoryName', 'M', 'TotalAmount', '', ' ORDER BY CategoryId');

ป.ล.

HDC V4.0 & Smart Card On Ubuntu

เนื่องจาก HDC ของกระทรวงสาธารณสุขได้ปรับปรุงเวอร์ชั่นใหม่ ทำให้การเข้าใช้งานระบบด้วย Smart Card ด้วย Linux แบบเดิมไม่สามารถทำได้ เคยเขียนวิธีใช้เวอร์ชั่นเดิมไว้ที่นี่ (HDC & Smart Card On Ubuntu)

ถ้าจากข้อมูลการปรับปรุงจะเห็นว่า

  • มีการใช้ HTTPS
  • มีการปรับปรุง Agent

ที่นี้เราจะเข้าใช้งานระบบด้วย Smart Card ด้วย Linux (ในที่นี้ใช้ Ubuntu 18.04)

  1. ทำการดาวน์โหลด Smart Card Agent เวอร์ชั่นปรับปรุง ทำการติดตั้งให้เรียบร้อย
  2. ตรวจสอบ Smart Card ในเครื่อง ถ้าพบเครื่องอ่าน Smart Card จะขึ้นหน้าตาแบบนี้ (กรณีไม่พบให้ทำการติดตั้งแพคเกจ sudo apt install pcscd pcsc-tools
  3. ทำการรัน Smart Card Agent ได้เลย (ข้ามเรื่องติดตั้ง JRE ไปเลยนะ ถ้าไม่มีก็ติดตั้งซะ)
    java -Dsun.security.smartcardio.library=/lib/x86_64-linux-gnu/libpcsclite.so.1 -jar JSmartCardReader.jar 8084

  4. เปิดหน้า Login ของ HDC ก็เป็นอันสามารถเข้าใช้งานได้ เคลียร์ !!!

ป.ล. ที่เปลี่ยนแปลงจากเวอร์ชั่นเดิม

  • Port ปรับมาใช้ 8084 ในตัว Agent
  • ใช้ HTTPS

 

การคำนวณระยะห่างระหว่างจุดสองจุด (Latitude/Longitude points) ใน MySQL

วันนี้เขียนบันทึกสั้น ๆ หล่ะกัน  ^_^

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

ในด้านสาธารณสุขเองก็เหมือนกันแผนที่ก็ยิ่งมีความสำคัญ อย่างเช่น การควบคุมแหล่งแพร่โรค (หมู่บ้านหรือชุมชน) ตัวนี้ก็ใช้เรื่องของแผนที่มาเกี่ยวข้องแต่ถึงอย่างงั้นก็ตามข้อมูลส่วนใหญ่ที่เราเก็บก็มักเป็นพิกัดละติจูด ลองจิจูด (Latitude/Longitude) และมีโปรแกรม/ทูลสักตัวมาทำงานคู่ด้วย

อย่ากระนั้นเลยบางทีสิ่งที่เราต้องการก็รอโปรแกรมหรือทูลมาทำงานได้ไม่ทันการณ์ ตัวอย่างเช่น “ขอรายชื่อ/บ้านของชาวบ้านที่อยู่ห่างจากบ้านที่พบผู้ป่วยไข้เลือดออกรัศมี 100 เมตร” แล้วสิ่งที่เรามี (พื้นฐาน) หล่ะมีอะไรบ้าง
– ข้อมูลพิกัดจาก HIS (Latitude/Longitude) มีเก็บ
– ทางเลือก โปรแกรม/ทูลก็ดีไปคลิก ๆ ค้นหา (มีเว็บ gisjhcis ให้ใช้นะครับ ตัวนี้ก็ใช้บริการ/API แผนที่จาก Google อีกต่อนึง) หรือคำนวณจากพิกัดที่เรามี
เรามันสายฮาร์ดคอร์อยู่แล้ว ทำเรื่องง่ายให้เป็นเรื่องยากสิ 5555 งั้นก็เริ่มกันเลย

  1. สร้างฟังก์ชั่นสำหรับการคำนวณระยะห่างจุดสองจุด (Latitude/Longitude points) ใน MySQL โดยใช้ Haversine formula รายละเอียดก็ไปอ่านต่อได้เลย
    DELIMITER $$
    DROP FUNCTION IF EXISTS haversine $$
    CREATE FUNCTION haversine (
            lat1 FLOAT, lon1 FLOAT,
            lat2 FLOAT, lon2 FLOAT
    ) RETURNS FLOAT
    NO SQL DETERMINISTIC
    BEGIN
        DECLARE r FLOAT unsigned DEFAULT 6372.8;
        DECLARE dLat FLOAT unsigned;
        DECLARE dLon FLOAT unsigned;
        DECLARE a FLOAT unsigned;
        DECLARE c FLOAT unsigned;
     
        SET dLat = RADIANS(lat2 - lat1);
        SET dLon = RADIANS(lon2 - lon1);
        SET lat1 = RADIANS(lat1);
        SET lat2 = RADIANS(lat2);
     
        SET a = POW(SIN(dLat / 2), 2) + COS(lat1) * COS(lat2) * POW(SIN(dLon / 2), 2);
        SET c = 2 * ASIN(SQRT(a));
        
        SET r = IF(htype = 'km', r, 3959);
        
        RETURN (r * c);
    END$$
     
    DELIMITER ;
  2. ลองทดสอบเรียกใช้งานฟังก์ชั่นดูจากพิกัดที่เรามี
    -- Ex
    SET @origin_lat0=15.829187;
    SET @origin_long0=105.262752;
    SET @origin_lat=15.828063;
    SET @origin_long=105.380678;
    
    SELECT ROUND(haversine(@origin_lat0, @origin_long0, @origin_lat, @origin_long), 2) AS distance_km;
    +-------------+
    | distance_km |
    +-------------+
    |       12.62 |
    +-------------+
    1 row in set (0.00 sec)
    
  3. ตรวจสอบว่าคลาดเคลื่อนมากน้อยแค่ไหน
  4. ทีนี้เราก็สามารถใช้ข้อมูลพิกัดจากตาราง house (ในที่นี้ใช้ HIS เป็น JHCIS ของกระทรวงฯ นะครับ) ได้เลย
  5. จบปิ๊งงงง ^_^

เพิ่มเติม
Fastest Way to Find Distance Between Two Lat/Long Points
Haversine formula
GISFORJHCIS

ป.ล.
เอาไปคำนวณระยะห่างระหว่างเราน่าจะไม่ได้

 

ปรับปรุงข้อมูลวันหยุดราชการ (Holiday) กัน

สำหรับประชาชนคนไทยแล้วคำว่า “ในเวลาราชการ” นี่น่าจะคุ้นเคยกันเป็นอย่างดี เรามักเห็นคำนี้ติดตามหน่วยงานราชการ แล้วคำว่าในเวลาราชการนี่มันยังไง เอาแบบกำปั้นทุบดิน ก็คือวันที่ไม่ใช่วันหยุดราชการนั่นแหล่ะ 😛

แล้ววันหยุดราชการนี่เราก็เริ่มยึดตาม “ประกาศกำหนดวันหยุดราชการนักขัตฤกษ์ พระพุทธศักราช ๒๔๕๖” ซึ่งพระบาทสมเด็จพระมงกุฎเกล้าเจ้าอยู่หัว รัชกาลที่ ๖ ทรงออกประกาศดังกล่าว ถ้าใครจะศึกษารายละเอียดบล็อกนี้ก็อธิบายไว้เป็นอย่างดี

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

และอีกเว็บไซต์ก็ myhora ซึ่งมีบริการ iCal บริการ

จะเห็นได้ว่ามีไฟล์ CSV (Comma-separated values) ให้เราได้ใช้ด้วย งั้นเราก็มาปรับปรุงวันหยุดราชการด้วยไฟล์ตัวนี้กัน

  1. เริ่มต้นก็ดาวน์โหลดมาซะ
    wget -O th_holiday.csv http://www.myhora.com/calendar/ical/holiday.aspx?2561.csv

    หน้าตาข้อมูลไฟล์คร่าว ๆ ก็ประมาณนี้

  2. นำเข้าข้อมูลข้างต้นลงในฐานข้อมูลของเราด้วยคำสั่ง LOAD DATA INFILE (สร้างตารางชั่วคราว th_holiday ไว้รอรับด้วย )
    DROP TABLE IF EXISTS th_holiday;
    CREATE TABLE IF NOT EXISTS th_holiday(
        Subject       	VARCHAR(255) NULL
        ,Start_Date    	DATE NOT NULL
        ,Start_Time    	TIME NULL
        ,End_Date      	DATE NULL
        ,End_Time      	TIME NULL
        ,All_day_event 	VARCHAR(4) NOT NULL
        ,Description   	VARCHAR(255) NOT NULL
        ,Show_time_as  	INTEGER  NOT NULL
        ,Location      	VARCHAR(30)
    );
    
    TRUNCATE th_holiday;
    LOAD DATA LOCAL INFILE 'th_holiday.csv' 
    INTO TABLE th_holiday
    FIELDS TERMINATED BY ',' 
    ENCLOSED BY '"'
    ESCAPED BY '"'
    LINES TERMINATED BY '\r\n'
    (`Subject`, @start_date, `Start_Time`, `End_Date`, `End_Time`, `All_day_event`, `Description`, `Show_time_as`, `Location`)
    SET start_date = STR_TO_DATE(@start_date, '%d/%m/%Y');
  3. เป็นอันเสร็จสิ้น ทีนี้ก็นำข้อมูลนี้ไปปรับปรุงในตารางของแต่ละ HIS

 

 

Dockerized Primitive Pictures – Reproducing images with vector-based geometric primitives

มีโปรเจคบน github ที่ใช้สร้างรูปภาพด้วย geometric primitives สำหรับใครที่ชอบรูปภาพแบบนี้จะรู้สึกแบบฟินมากที่มีโปรเจคนี้ขึ้นมา ปรบมือให้เลยหล่ะกัน ? ? ? ? ?
ภาพ geometric primitives คือ ? จะอธิบายไงดีให้ภาพมันอธิบายตัวเองหล่ะกัน

รูปใหญ่ ๆ ก็จะประมาณนี้ สวยใช่ไหมล่ะ ^_^

ใครอยากตามไป Fork ก็ตามนี้เลย https://github.com/fogleman/primitive  ส่วนเราก็มาลองสร้าง Docker กัน

  1. เราใช้ Image จาก Go (golang) is a general purpose, higher-level, imperative programming language
FROM golang:alpine
MAINTAINER M
LABEL version="latest"

RUN apk add --no-cache git && \
mkdir -p /opt && cd /opt && \
go get -u github.com/fogleman/primitive

VOLUME /opt
WORKDIR /opt

CMD ["/bin/sh"]
  • มาลองใช้งานกัน
    docker run -it --rm -v /path/data:/opt primative:alpine primitive -i input.png -o output.png -n 100
  • มาดูผลลัพธ์กัน
  • ชอบ ๆ ๆ ????

Dockerized (SQLiv) massive SQL injection

SQLiv
Massive SQL injection scanner

FROM alpine:latest
MAINTAINER M
LABEL version="latest"

RUN apk add --no-cache python py-pip openssl git && pip install --upgrade pip && \
rm -rf /var/cache/apk/* && \
mkdir -p /opt && cd /opt && git clone https://github.com/Hadesy2k/sqlivulscan.git && \
cd /opt/sqlivulscan && \
chmod 755 /opt/sqlivulscan/setup.py && \
python2 setup.py -i

RUN rm -rf /opt && chmod 755 /usr/share/sqliv/sqliv.py

WORKDIR /usr/share/sqliv

ENTRYPOINT ["python", "sqliv.py"]
CMD ["--help"]

ป.ล.

  • ไว้ใช้สำหรับหาข้อผิดพลาดเพื่อป้องกัน ไม่แนะนำให้ใช้มีดแทงตัวเอง นะจ๊ะ นะจ๊ะ
  • อยู่ในแลปช่วงหัดเขียน Dockerfile
  • ข้อมูลเพิ่มเติมที่ https://en.kali.tools/all/?tool=1334
  • build เอาหล่ะกันนะจ๊ะ นะจ๊ะ

 

การติดตั้ง Server สำหรับ JHCIS ด้วย Linux Ubuntu 17.04

**บล็อกนี้ยาวเลยทีเดียว เอาเป็นว่าตัดแบ่งออกเป็น 4 ตอนหล่ะกันนะ จะพยายามเขียนให้จบเร็วที่สุด ^_^
I. เกริ่นหน่อย
II. การติดตั้ง(รวมถึงการย้ายข้อมูลจากระบบเดิม)
III. การปรับแต่งให้ระบบ (Server, MySQL) ให้ได้ประสิทธิภาพที่ดีขึ้น
IV. การติดตั้งระบบอื่นเพื่อการสนับสนุนระบบการทำงานของหน่วยบริการ

ที่มาและเหตุผล ….

ดูเป็นทางการกันเลยทีเดียว แต่ความเป็นจริง ๆ แล้วมันก็มาจากเหตุผลบ้าน ๆ นั่นแหล่ะว่าเพราะมันมีปัญหา แล้วปัญหาก็คือ

  • ข้อมูลการให้บริการในแต่ละวันมีปริมาณเยอะขึ้น รวมกับของเก่าที่เป็นข้อมูลที่เคยให้บริการมามันก็เยอะขึ้นเรื่อย ๆ พออะไร ๆ มันเยอะขึ้น สิ่งที่ต้องทำก็มากขึ้น (คน + เครื่อง) เพราะงั้นสเกลในระดับเดิม ๆ ที่เคยทำมามันก็เริ่มรองรับไม่ได้แล้ว เป็นเรื่องธรรมดา
  • มีเกณฑ์ระบบเทคโนโลยีสารสนเทศของ รพสต.ติดดาว อันนี้คือปัญหาใช่ไหม 555 ถ้าเราดูเกณฑ์แล้วมันก็เป็นเรื่องที่ควรทำนั่นแหล่ะ

    เครื่องแม่ข่าย (Server) ก็ควรทำหน้าที่ให้บริการในระบบเครือข่ายแก่เครื่องลูกข่าย (Client) ถึงแม้เดิมทีทรัพยากรในหน่วยบริการจะมีจำกัด จนต้องทำเครื่องเป็น Server ในโหมด Developer  มานานนมละจนหลายคนเข้าเข้าใจว่าเครื่องที่ลงโปรแกรม JHCIS Server คือ Server จริง ๆ ในรูปแบบ Client – Server
  • พฤติกรรมใช้งาน พบว่าระบบปฏิบัติการ (Windows) เจ๊ง ติดไวรัส ไฟล์ถูกเข้ารหัส โปรแกรมติดหนอน ระบบทำงานช้า ส่วนหนึ่งมาจากพฤติกรรมใช้งานของผู้ใช้งานที่ไม่ระมัดระวังเอง ยิ่งเครื่องถูกใช้จากมากหน้าหลายตา ความเสี่ยงก็ยิ่งเพิ่มขึ้นมากเท่านั้น คุณแสกนไวรัสก่อนเปิดแฟลชไดร์ฟรึยัง ?
  • ข้อจำกัดของระบบปฏิบัติการที่ใช้งานอยู่ เชื่อแน่ว่าเกิน 90 % เครื่องทำงานบนระบบปฏิบัติการวินโดวส์ (ตอนนี้เวอร์ชั่น 10 อัพเดทกันรึยัง) สำหรับวินโดวส์เองมีมีรุ่นที่ใช้งานเป็น Server แต่ด้วยราคาและความยากในการสรรหา ดูราคาในท้องตลาดกัน

    ส่วนใหญ่ที่ใช้งานก็เป็นกลุ่ม Desktop Edition มันก็เหมาะเป็น Desktop นั่นแหล่ะ เราขืนใจระบบมากไป
  • อยากได้ Server ที่เสถียร (เหงาใช่ไหมจะไปหา ♪♪ จะไปเช็ดน้ำตาให้ตอนนี้
    เคยเป็นเพื่อนมาอย่างไร ก็ยังเป็นทุกนาที ♪♪ ตึ่งโป๊ะ) ส่วนใหญ่แล้วระบบปฏิบัติการที่ใช้ในกลุ่ม Server ก็จะเป็น *nix (Linux UNIX บลาาาา) สรุปคือมันดี อึด ถึก ทน เหมาะ สำหรับการประมวลผลและให้บริการในเครือข่าย #ทำไมมันดีจัง แต่… มันก็ต้องแลกมาด้วยความยากและระยะเวลาการเรียนรู้ ระบบปฏิบัติการนี้ก็เลยจำกัดอยู่ในกลุ่มเล็ก ๆ กลุ่มที่ทำงานด้านคอมพิวเตอร์ แต่…ทุกอย่างก็ง่ายขึ้นเมื่อมี Ubuntu

Ubunu คืออะไร

อูบุนตู (Ubuntu) เป็นระบบปฏิบัติการคอมพิวเตอร์ที่เป็นระบบปฏิบัติการแบบเปิดซึ่งมีพื้นฐานบนลินุกซ์ดิสทริบิวชันที่พัฒนาต่อมาจากเดเบียน การพัฒนาสนับสนุนโดยบริษัท Canonical Ltd ซึ่งเป็นบริษัทของนายมาร์ก ชัทเทิลเวิร์ธ ชื่อของดิสทริบิวชันนั้นมาจากคำในภาษาซูลู และภาษาโคซา (ภาษาในแอฟริกาใต้) ว่า Ubuntu ซึ่งมีความหมายในภาษาอังกฤษคือ “humanity towards others”


Ubuntu เป็น Linux ที่ถูกหลอมลวมจากความเสถียรและความง่ายในการใช้งานเข้าด้วยกัน (เรากำลังพูดถึง Desktop Edition นะ ส่วน Server Edition ก็ละไว้สำหรับกลุ่มแอดมินเค้าเหอะ ส่วนเรื่องการปรับแต่งประสิทธิภาพบางส่วนเพื่อทำให้เครื่องที่ใช้ Ubuntu เหมาะสำหรับ Server อยู่ท้าย ๆ นะ)

ช่วงรอตอนที่ 2 ก็โหลดไฟล์ติดตั้งรอเลยนะ ดาวน์โหลด Ubuntu Desktop (ใช้ Ubuntu GNOME หล่ะกัน) เวอร์ชั่น ณ ปัจจุบันจะเป็น 17.04 (Zesty Zapus Support until 2018-01)

การติดตั้ง Ubuntu GNOME 17.04

  1. หลังจากดาวน์โหลดไฟล์ติดตั้งมาแล้วก็ทำการสร้างตัวติดตั้งจาก USB ได้เลย ในที่นี้จะใช้โปรแกรมชื่อ Rufus (ปัจจุบัน Version 2.17) ขั้นตอนก็ไม่ซับซ้อนเลือกไฟล์ ubuntu-gnome-17.04-desktop-amd64.iso แล้วก็กดปุ่ม start เลย (ภาพ screen shot จากเว็บอ่ะนะ)
  2. เรียบร้อยจากขั้นตอนที่ 1 ก็เริ่มติดตั้งกัน หน้าจอแรกจะขึ้นมาให้เราเลือก
    – Try Ubuntu GNOME กรณีอยากเล่นเนตชิล ๆ ไปด้วยก็เลือกตัวนี้ได้แล้วค่อยกด Install ต่อได้เหมือนกัน
    – Install Ubuntu GNOME
  3. ขึ้นหน้าจอเตรียมการติดตั้ง กรณีเนตแรงและต้องการลดระยะเวลาการติดตั้งก็ติ๊ก Download ตามภาพ
  4. พอกด Continue จะขึ้นหน้าจอเตรียมฮาร์ดดิสก์สำหรับติดตั้ง มีตัวเลือก
    – Erase disk and install Ubuntu GNOME ตัวเลือกนี้ระบบติดตั้งจะเตรียมดิสก์แบบฉันคิดให้นะ นายไม่ต้องทำไร
    – Something else  ส่วนตัวนี้ก็ตรงข้ามกับข้างบน นายทำเองอยากได้แบบไหนก็จัดเลย

    เราก็เลือกแบบที่ 2 สิ 555 คือต้องบอกเบื้องต้นก่อนว่าเครื่องมีฮาร์ดดิสก์ 2 ลูก
    – ลูกแรก ขนาด 10 GB ไว้ติดตั้งตัว OS (Ubuntu)
    – ลูกที่สอง ขนาด 1 GB ไว้เก็บไฟล์สำรองจากระบบสำรอง (เดี๋ยวจะกล่าวถึงในตอนที่ 4 แต่ก็เตรียมไว้เบื้องต้นตามนี้)
  5. เริ่มทำการแบ่งพาร์ติชั่น ปกติเราจะแบ่งออกเป็น
    – /boot ขนาด 1 GB
    – swap ขนาด 1 GB
    -/ (root)
    มีเพิ่มคือเราแยกพาร์ติชั่น /var และสร้างพาร์ติชั่น /data ในฮาร์ดดิสก์อีกลูก ส่วนใครสงสัยว่าจะใช้ขนาดเท่าไหร่ในแต่ละพาร์ติชั่นก็ไปอ่านได้ตามนี้
    ส่วนตัวเลือกตรงคอมโบบ็อกซ์ Device for boot loader installation ก็ให้เลือกฮาร์ดดิสก์ตัวแรกไป
  6. กด Install Now จะขึ้นหน้าจอให้เลือก Location เราคนไทยก็เลือก Bangkok ไป
  7. กด Continue ก็เลือก Keyboard Layout ซึ่งจะสัมพันธ์กับข้อที่แล้ว ฉลาดเน๊อะ
  8. กด Continue จะให้ใส่ข้อมูลชื่อผู้เข้าใช้งาน รหัสผ่านและชื่อเครื่อง ส่วนจะใส่อะไรไปก็จำให้ดี ๆ ส่วนชื่อเครื่องเองก็มีผลกับเรื่องของ Host name ในระบบเครือข่ายด้วย
  9. พอกด Continue ไปก็จะเริ่มการติดตั้งตัว Ubuntu GNOME ง่ายไหม ^_^ ก็รอ สำหรับใครที่เลือก Try Ubuntu GNOME ในข้อแรกก็สามารถเล่นอินเตอร์เนตชิล ๆ รอได้เลย
  10. เมื่อทำการติดตั้งเสร็จก็จะแสดงหน้าจอแบบนี้ ยินดีด้วยทุกอย่างกำลังไปได้สวย

    กด Restart ได้เลย

    พร้อม ๆ กับที่ระบบให้เราถอด USB ตัวติดตั้งออกและกด ENTER ต่อเพื่อเริ่มต้นระบบใหม่
  11. ช่วงระหว่างการรอการบูตมีประเด็นที่ทำไมต้องเลือก Ubuntu GNOME 17.04
    – แรกเลยคือต้องการความสด ณ ปัจจุบันเวอร์ชั่นนี้คือเวอร์ชั่นล่าสุดที่ Ubuntu สร้างออกมาสิ่งที่จะได้คือเคอร์เนล 4.10 แหล่ะ อันนี้ใหม่ชัวร์รวมทั้งแพคเกจ/โปรแกรม ต่าง ๆ (ส่วนเราเองก็ใช้ 17.10 แบบ Daily build อยู่เลย)
    – เวอร์ชั่นนี้ไม่ใช่ Long term support (LTS) releases are for 5 years. นั่นหมายความว่าเราจะได้รับการซัพพอร์ตแค่ 9 เดือน สำหรับรุ่น Regular ซึ่งก็คือหมดในเดือนมกราคม 2018 นั่นเอง สำหรับใครที่ต้องการการซัพพอร์ตยาว ๆ ก็สามารถเลือกเวอร์ชั่น 16.04 ซึ่งตอนนี้ปรับปรุงเป็น 16.04.3 แล้ว ตัวนี้เป็น LTS
    – ทำไมไม่ใช้ Server Edition ถ้าจะทำ Server ประเด็นนี้ก้ำกึ่งเราอธิบายแบบนี้หล่ะกัน ประเด็นแรก ด้วยความที่ JHCIS ถูกใช้ในหน่วยบริการปฐมภูมิ (รพ.สต.) เป็นส่วนใหญ่ ผู้ที่ใช้งานก็เป็นพยาบาล นักวิชาการสาธารณสุข ทันตาภิบาล พนักงานบันทึกข้อมูล คนงาน ในพื้นที่ห่างไกล ไม่มีหรอกนักคอมพิวเตอร์หรือกลุ่มคนด้านนี้เฉพาะ อาจจะมีบ้างที่เป็น Power User ที่สนใจเรื่องนี้ แต่ความคุ้นชินกับระบบการติดต่อแบบคอมมานไลน์นี่คงยากและลำบากเกินไป (อันนี้ขอระบายหน่อย รพ.สต ในอำเภอเราไกลสุด ~38 กิโลเมตร การสนับสนุนมันทำได้จำกัด จำกัดมาก ๆ T_T) ภาพนี้เป็นวันที่เราออกไปช่วยติดตั้งระบบนี้แหล่ะ ไม่ใช่ รพ.สต.ที่ไกลสุดนะ แต่ไปเส้นทางนี้แหล่ะ หมอกเต็มเลย

    ประเด็นที่สอง ถ้าเราอยากให้ผู้ใช้งาน/คนใช้ไม่ต่อต้านมากไป อย่าทำให้มันยากเกินไปสำหรับการเรียนรู้ วันนึงข้างหน้าเราอาจะเห็น รพ.สต.ใช้ LibreOffice แทน Microsoft Office ใช้ Openshot ตัดต่อวิดีโอออกเยี่ยมผู้ป่วย ก็ได้ ตอนนั้นถนนในประเทศเราคงปูด้วยทองคำไปละ
    – ถ้าไม่อยากใช้ Server Edition แบบคอมมานด์ไลน์ก็มี Cent OS มี Debian มี Open SUSE  บลา ๆ ที่จริงมันมีมากกว่าความชอบนะ ถ้าสังเกตจากความนิยมแล้ว Debian Base จะได้รับความนิยมสูงสุด
  12. พอเริ่มต้นระบบใหม่อีกครั้งจะขึ้นหน้าจอแบบนี้ก็เริ่มใช้งานได้เลย ชื่อผู้ใช้และรหัสผ่านก็ที่ตั้งไว้จากก่อนหน้านี้
  13. ถึงขั้นนี้ก็ยังต้องทำเพิ่มนิดหน่อย ถ้าเปรียบเหมือน Windows นี่ก็แค่เพิ่งติดตั้ง OS เสร็จแค่นั้น ยังไม่มีแพคเกจ/โปรแกรมที่เราจำเป็นต้องใช้สำหรับทำเป็น JHCIS Server เลย ซึ่งแพคเกจที่เราจะทำการติดตั้งและจำเป็นต้องใช้มีดังนี้
    – MySQL Server ตัวนี้เป็น RDBMS  สำหรับเก็บข้อมูลจากโปรแกรม JHCIS
    – MySQL Workbench สำหรับติดต่อกับ MySQL Server แบบ GUI
    – TeamViewer สำหรับทำ Remote Desktop กรณีที่ต้องขอความช่วยเหลือจากคนใจดี
    – แพคเกจอื่น ๆ ที่จำเป็น
    โดยเริ่มต้นก็ทำการเปิดโปรแกรม Terminal ขึ้นมา (เลี่ยงไม่ได้นะ ยังไงก็ต้องได้ใช้คอมมานด์ไลน์บ้าง แต่ก็จะพยายามให้น้อยที่สุดหล่ะกัน)


    เริ่มคำสั่งแรกเลยคือทำการอัพเดตระบบซะ (sudo ก็คือใช้สิทธิ์ของผู้ดูแลระบบซึ่งก็คือคนติดตั้งนั่นแหล่ะ ก็กรอกรหัสผ่านไปอีกครั้ง)

    sudo apt update && sudo apt upgrade -y

    ติดตั้ง MySQL Server ในที่นี้เราจะใช้เวอร์ชั่น 5.7 (นี่ก็ใหม่ เราอยากได้ของสดอยู่แล้วหนิ ^_^) การติดตั้งเพื่อให้ง่ายเราจะใช้ตัวช่วยนั่นก็คือ tasksel

    sudo apt install tasksel
    sudo tasksel

    จะขึ้นหน้าจอสำหรับเลือกแพคเกจ/โปรแกรม

    ให้เลือกเลือกแพคเกจ/โปรแกรม ตามนี้ (เดี๋ยวจะได้ใช้นะครับ จะอธิบายทีหลัง)
    – LAMP Server
    – Samba File Server
    – Ubuntu GNOME Desktop (อันนี้เลือกอยู่ก่อนหน้าแล้ว)
    – OpenSSH Server
    – Basic Ubuntu Server
    การเลือก/ยกเลิก ก็กด Space Bar นะ แล้วก็กด Tab มาที่ <ok>

  14. จะขึ้นหน้าจอการติดตั้งแพคเกจ/โปรแกรมที่เราเลือก

    พอถึงขั้นตอนการติดตั้ง MySQL Server ก็ให้ระบุ Password ของผู้ใช้งาน root (คนที่ใหญ่สุดในโปรแกรม MySQL)

    แล้วก็ยืนยัน Password เดิม

    ** ประเด็นเรื่อง Password ของ root นี่ ขอพูดนิดนึงนะ ส่วนจะทำตามหรือไม่ก็คงอีกเรื่อง ผลกระทบมันก็เรื่องความเสี่ยง/ความปลอดภัยของข้อมูลเป็นหลัก โดยปกติในฐานะของผู้ดูแลระบบฐานข้อมูล (Database Administrator) Password ของ root จะต้องเดายาก เข้าถึงได้เฉพาะผู้ดูแล ส่วนโปรแกรมอื่น/ระบบอื่น/ผู้ใช้งานอื่น ก็สร้าง User ให้พร้อมกำหนดสิทธิ์/ระดับการใช้งาน ให้ทีหลัง User root แทบที่จะไม่ถูกนำมาใช้ในระดับอื่นเลยนอกจาก Administrator อย่างเดียว ปกติระบบจริง ๆ ที่เน้นความปลอดภัยก็ทำกันในลักษณะนี้นะ เอาเป็นว่าได้พูดแล้วนะแล้วแต่หล่ะกันระบบใครระบบมัน ^_^
  15. เมื่อติดตั้งแพคเกจ/โปรแกรม เสร็จเรียบร้อยลองมาตรวจดูว่า MySQL Server ซึ่งเป็นตัวเอกของบทความนี้ถูกติดตั้งไปรึยังและทำงานได้ไหม
    sudo systemctl status mysql

    กรณีที่ไม่มีอะไรผิดพลาดจะขึ้นหน้าจอนี้ เป็นอันว่าใช้ได้

  16. ที่นี้ก็ติดตั้งโปรแกรม MySQL Workbench ต่อได้เลย (ควรมีนะถ้าอยากเลี่ยงคอมมานด์ไลน์) โดยการกดที่ Software และค้นหาตามภาพ เจอก็กด Install

    เสร็จแล้วก็ลองเปิดเข้าใช้งานหน้าตาคร่าว ก็ตามรูป เป็น MySQL Client อีกตัวหนึ่ง (Official จาก MySQL)
  17. ทำการติดตั้งแพคเกจอื่น ๆ ที่จำเป็น
    sudo apt install pv gdebi

  18. ทำการติดตั้ง TeamViewer เพื่อใช้สำหรับ Remote Desktop กรณีต้องการความช่วยเหลือ (คาดหวังให้ทำ DDNS หรือ VPN ไว้นี่คงยากหน่อย T_T)
    โดยให้ Download โปรแกรมจากเว็บไซต์ ปัจจุบันเวอร์ชั่น v12.0.85001 (deb 32-Bit / 64-Bit Multiarch)

    sudo dpkg --add-architecture i386
    sudo apt update
    sudo dpkg -i teamviewer_i386.deb
    


    เรียกใช้งานก็จะขึ้นหน้าจอแบบนี้ (License ก็จะเป็น Non-Commercial มันก็จำกัดแหล่ะ ถ้าอยากใช้ระยะยาวก็ซื้อนะ )

  19. ทีนี้ก็เหลือการย้ายข้อมูลจากระบบเดิมขึ้นระบบใหม่
    ช่วงรอตอนที่ 2/2 ก็ลองติดตั้งกันดูนะครับ ติดปัญหาอะไรก็ลอง ๆ Discus กันได้ หรือมีคำแนะนำอื่น ๆ เพิ่มเติมก็ยินดี ^_^
  20. ก่อนย้ายข้อมูลจาก JHCIS เครื่องเดิม เรามาดูโครงสร้างฐานข้อมูล jhcisdb กันก่อน จะเห็นว่าฐานข้อมูลประกอบไปด้วย ตาราง (Tables), Stored Procedures, Functions เพราะฉะนั้นขั้นตอนการส่งออก/นำเข้า ก็ต้องให้สิ่งเหล่านี้ออกไปด้วยและนำเข้าให้ครบถ้วน

    เมื่อพร้อมก็เริ่มกันเลย Tool ที่ใช้เราจะใช้ mysqldump

    mysqldump --user=<USER NAME> -p --host=<HOST NAME/IP Address> --port=<PORT> --add-drop-database --add-drop-table --max_allowed_packet=1G --default-character-set=utf8 --skip-lock-tables --routines --events --triggers --single-transaction --databases "jhcisdb" &gt; jhcisdb.sql

    ก็ให้ระบุ ค่าที่ถูกต้องแทนตัวแปรในคำสั่ง
    <USER NAME> : ถ้าเดิม ๆ ก็จะเป็น root นั่นแหล่ะ
    <HOST NAME> : ชื่อเครื่อง JHCIS Server เดิมหรืออาจระบุเป็น IP Address ก็ได้เช่นกัน
    <PORT> : เดิม ๆ เป็น 3333 ในกรณีที่ไม่เปลี่ยนแปลงมาก่อน
    รันคำสั่งเสร็จก็รอ รอ ^_^  ส่วนพารามิเตอร์ที่ใช้สามารถอ่านเพิ่มเติมได้ที่นี่

  21. เมื่อได้ไฟล์ส่งออกมาเรียบร้อยแล้ว ก็เริ่มขั้นตอนการจัดการ JHCIS Server เครื่องใหม่ ปกติแล้วเราก็มักจะสร้าง User และจัดการเรื่องสิทธิ์การใช้งาน ก่อน ทั้งนี้ทั้งนั้นจำเป็นต้องรันคำสั่ง เพื่อกำหนดค่าความปลอดภัยเบื้องต้นของ MySQL Server
    sudo mysql_secure_installation

    ถัดมาก็สร้างฐานข้อมูล (คำสั่ง ของ mysqldumpด้านบนจะเพิ่มการสร้างฐานข้อมูลด้วย ถ้ามันไม่มีอยู่นะ แต่เราสร้างเองก็ได้)

    CREATE SCHEMA `jhcisdb` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;

    ตามด้วยการกำหนดสิทธิ์การเข้าใช้งานฐานข้อมูล

    CREATE USER 'user_name'@'localhost' IDENTIFIED BY 'password';
    CREATE USER 'user_name'@'%' IDENTIFIED BY 'password';
    GRANT ALL PRIVILEGES ON jhcisdb.* TO 'user_name'@'localhost';
    GRANT ALL PRIVILEGES ON jhcisdb.* TO 'user_name'@'%';
    FLUSH PRIVILEGES;

    แล้วเราก็นำเริ่มเข้าฐานข้อมูล jhcisdb กัน

    mysql -u<user_name> -p jhcisdb < jhcisdb.sql

    ถ้าไม่มีอะไรผิดพลาดก็ลองเช็ค ตาราง (Tables), Stored Procedures, Functions ดูครบถ้วน JHCIS Server เครื่องใหม่ก็พร้อมใช้งาน

  22. ถัดมาก็ลองเปิดโปรแกรม JHCIS Client แล้วกำหนดค่าการเชื่อมต่อฐานข้อมูลใหม่ เป็นเครื่องที่เราสร้างใหม่ตะกี้ ถ้าสามารถใช้งานได้
    ** ปกติพอร์ตมาตรฐานของ MySQL จะเป็นพอร์ต 3306 กรณีเราไม่ได้เปลี่ยนแปลงค่าคอนฟิกใด ๆ
    ** มีบางเครื่องที่เข้าใช้งานแล้ว JHCIS แจ้งเตือนหน้าจอแบบนี้

    ก็ไม่ต้องตกใจไปนะ ให้เช็คเบื้องต้นดังนี้คือ
    – ในฐานข้อมูล jhcisdb มีตาราง _tmpicd10% หรือไม่ ถ้ามีก็ไม่มีอะไรให้ตกใจ

    – ให้ทำการสร้างตาราง p เปล่า ๆ ขึ้นมาเพื่อแก้บัคก่อน (ตารางนี้ไม่มีผลกับการบันทึกอะไร เพียงแต่ทำให้ Code ไม่หลุดเข้า try-catch เฉย ๆ)
    – ให้ทำการ Disable strict mode ใน MySQL Server เพื่อให้ compatible กับ MySQLเวอร์ชั่นเก่า ตามลิงค์นี้
    – เบื้องต้นก็ได้รายงาน/สอบถามไปทางอาจารย์สัมฤทธิ์แล้วนะครับ ^_^

การปรับแต่งให้ระบบ (Server, MySQL) ให้ได้ประสิทธิภาพที่ดีขึ้น

เดิม ๆ แล้ว Ubuntu หรือ Linux ดิสโทรอื่น ๆ เองเป็นระบบปฏิบัติการที่ถูกสร้างมาแบบ “out-of-box”  หมายความว่ามันเพียงพอสำหรับการใช้งาน แต่ถ้าต้องการรีดประสิทธิภาพให้ได้ออกมาเต็มที่ก็จำเป็นต้องปรับแต่งเพิ่มเติม

 ซึ่งผู้ใช้งานก็ต้องยอมรับความเสี่ยงข้อนึงว่ามันมีสิทธิ์ที่จะบูตเครื่องไม่ขึ้นเลยก็ได้ เพราะฉะนั้นก็ทำด้วยความระมัดระวังนะครับ หรือถ้าพอใจประสิทธิภาพที่ใช้งานอยู่ ณ ปัจจุบันก็ข้ามเซคชั่นนี้ไปเลยก็ได้ เตือนละน้าาาา ^_^ 

 

Sysctl Tweaks

ไฟล์ sysctl.conf เป็นไฟล์ที่เกี่ยวข้องกับเคอร์เนลโดยตรงฉะนั้น อยากให้กลับไปอ่านย่อหน้าตะกี้อีกรอบนะ เราสามารถแก้ไข้ไฟล์ sysctl.conf ได้ โดยการเปิดด้วย Text Editor ทั่ว ๆ ไป เอาที่ถนัดนั่นแหล่ะ

sudo gedit /etc/sysctl.conf

หน้าตาตอนจะแก้ไข ก็ประมาณนี้

และทำการเพิ่มรายการต่อไปนี้ลงท้ายสุดของไฟล์

### IMPROVE SYSTEM MEMORY MANAGEMENT ###

# Increase size of file handles and inode cache
fs.file-max = 2097152

# Do less swapping
vm.swappiness = 10
vm.dirty_ratio = 50
vm.dirty_background_ratio = 2

### GENERAL NETWORK SECURITY OPTIONS ###

# Number of times SYNACKs for passive TCP connection.
net.ipv4.tcp_synack_retries = 2

# Allowed local port range
net.ipv4.ip_local_port_range = 2000 65535

# Protect Against TCP Time-Wait
net.ipv4.tcp_rfc1337 = 1

# Decrease the time default value for tcp_fin_timeout connection
net.ipv4.tcp_fin_timeout = 15

# Decrease the time default value for connections to keep alive
net.ipv4.tcp_keepalive_time = 300
net.ipv4.tcp_keepalive_probes = 5
net.ipv4.tcp_keepalive_intvl = 15

### TUNING NETWORK PERFORMANCE ###

# Default Socket Receive Buffer
net.core.rmem_default = 31457280

# Maximum Socket Receive Buffer
net.core.rmem_max = 12582912

# Default Socket Send Buffer
net.core.wmem_default = 31457280

# Maximum Socket Send Buffer
net.core.wmem_max = 12582912

# Increase number of incoming connections
net.core.somaxconn = 4096

# Increase number of incoming connections backlog
net.core.netdev_max_backlog = 65536

# Increase the maximum amount of option memory buffers
net.core.optmem_max = 25165824

# Increase the maximum total buffer-space allocatable
# This is measured in units of pages (4096 bytes)
net.ipv4.tcp_mem = 65536 131072 262144
net.ipv4.udp_mem = 65536 131072 262144

# Increase the read-buffer space allocatable
net.ipv4.tcp_rmem = 8192 87380 16777216
net.ipv4.udp_rmem_min = 16384

# Increase the write-buffer-space allocatable
net.ipv4.tcp_wmem = 8192 65536 16777216
net.ipv4.udp_wmem_min = 16384

# Increase the tcp-time-wait buckets pool size to prevent simple DOS attacks
net.ipv4.tcp_max_tw_buckets = 1440000
net.ipv4.tcp_tw_recycle = 1
net.ipv4.tcp_tw_reuse = 1

กรณีที่ต้องการแก้ไขอื่นเพิ่มเติมหรืออยากรู้แหล่ะมันคืออะไร ผลจากบรรทัดนั้นจะได้อะไรตามไปอ่านได้ที่นี่

แล้วก็เริ่มใช้ค่าใหม่ได้เลยโดยใช้คำสั่ง sysctl -p หรือถ้าอยากลองว่ามันรอดไหมออกหมู่หรือจ่าก็สั่ง Reboot เครื่องได้เลย

MySQL Performance Tuning and Optimization

เครื่องนี้เป็น Database Server การจะไม่ปรับความสามารถของ MySQL ดูจะเป็นเรื่องที่บาปพอสมควร -*- แต่ก็เตือนไว้อีกนั่นแหล่ะ ไม่ระวังก็มีผลทำให้ MySQL Server Start ไม่ขึ้นกันเลยทีเดียว ถ้าอยากได้เอกสาร/บทความอ่านก่อนหน้าปรับจริงก็ตามไปอ่านได้ที่นี่ อื่น ๆ เพิ่มเติม ก็ไปทำลิงค์ข้างล่างได้เลย

การปรับแต่งความปลอดภัยและ Firewall

Firewall คือ ระบบรักษาความปลอดภัยของเครื่องคอมพิวเตอร์ (อ่านว่า ไฟร์วอลล์) ไม่ให้ถูกโจมตีจากผู้ไม่หวังดีหรือการสื่อสารที่ไม่ได้รับอนุญาต ซึ่งส่วนใหญ่จะมาจากระบบเครือข่ายอินเตอร์เน็ต รวมถึงเครือข่าย LAN ด้วย ซึ่งในปัจจุบัน Firewall มีทั้งอุปกรณ์ที่เป็น Hardware และ Software

ในที่นี้เราจะใช้ Software ที่ติดมากับ Linux/Ubuntu แต่ใช้ Tool จัดการที่มันง่ายขึ้น เริ่มต้นก็ติดตั้งแพคเกจ gufw

sudo apt install gufw
sudo gufw

สิ่งที่เราควรทำคือเปิดเฉพาะสิ่งที่ต้องใช้ ง่ายไหม ^_^  โดยการคลิกที่ Rules > Add (+) ในที่นี้เราอนุญาตเฉพาะบริการ MySQL และ SSH

ในกรณีที่ใครคุ้นชินกับ iptableก็ทำได้เฉกเช่นเดียวกัน ^_^

Automatically backup MySQL database to Google Drive

ประเด็นหลัก ๆ ของบล็อกนี้ก็เรื่องของการสำรองฐานข้อมูลนั่นแหล่ะ ต่างกันนิดหน่อยกับคำว่าตัวสำรอง เราสำรองเพราะเห็นว่าสิ่งนั้นสำคัญแต่ตัวสำรองคือยังไม่สำคัญนะให้รอ ก็ได้แค่นั้นแค่ตัวสำรอง

เดี๋ยวลองไล่ลำดับ ขั้นตอนในกระบวนการนี้ด้วยกัน

  1. เริ่มสำรองข้อมูล ในที่นี้คือฐานข้อมูลของ MySQL ด้วย Tool มาตรฐานคือ mysqldump (ส่วนเรื่องพารามิเตอร์ในคำสั่ง อะไรยังไง จะเอาอะไร ไม่เอาอะไร อ่านต่อได้ที่นี่)
  2. บีบอัดไฟล์ให้ขนาดเล็กลง
  3. เก็บไฟล์ไว้ที่เครื่องโลคอลนิดหน่อยอีก 30 วันค่อยมาลบหล่ะกัน (ทั้งนี้ทั้งนั้นก็ขึ้นกับความต้องการด้วยนะว่าเหมาะสมแค่ไหน)
  4. ทำการอัพโหลดข้อมูลที่สำรองได้ขึ้น Google Drive ผ่าน Google Drive CLI Client ตัวนึงที่ชื่อว่า gdrive (จุดประสงค์หลักคือเพื่อให้มีแหล่งเก็บอื่นเพิ่ม) ก่อนการใช้งานจำเป็นต้องอนุญาตให้ gdrive สามารถเข้าถึง Google Drive ของเราได้ก่อน
    1. อนุญาตสิจ๊ะ
    2. คัดลอก Token ที่ได้ เพื่อมาใช้ในโปรแกรม
  5. ทั้งหมดทั้งมวลให้ทำงานอัตโนมัติ โดยการใช้ crontab (สงสัยวิธีใช้งานก็ตามอ่านกันที่นี่นะ #เหมือนจะขี้เกียจ #55555)

โดยขั้นตอนข้างต้นเราเขียนเชลล์สคริปท์สั้น ๆ สำหรับทำงานแบบรูทีนตามนี้

ผลลัพธ์ที่ได้ก็ตามนี้

ป.ล. 1
การสำรองข้อมูลเป็นเรื่องที่สำคัญพอ ๆ กับการทดสอบไฟล์ที่สำรองได้นั้นสามารถใช้งานได้หรือไม่

ป.ล 2
gdrive – gdrive is a command line utility for interacting with Google Drive.
pv – monitor the progress of data through a pipe.

 

Smart Card Reader เสียรึเปล่าเนี่ย ?

Smart Card Reader เสียรึเปล่าเนี่ย ?

คำถามแรกเลยเวลาที่เปิดใช้งานโปรแกรมที่จำเป็นต้องติดต่อกับ Smart Card (สำหรับหน่วยงานราชการเกี่ยวกับเงิน ๆ ทอง ๆ นี่หลายโปรแกรมกันเลยทีเดียวเชียว) แล้วผลปรากฏว่า นิ่ง นิ่ง โปรแกรมไม่อ่านการ์ด/บัตร แล้วก็จะเกิดคำถามต่อ ๆ มา

  • Driver เครื่องอ่านติดตั้งรึยัง ติดตั้งแล้วใช้ได้ไหม
  • โปรแกรมต้องการคอมโพเนนท์/ไลบรารี่อะไรเพิ่มเติมอีกไหม
  • การ์ด/บัตร ยังอ่านได้ไหม มันเลือนไปอ่านไม่ได้เหมือนหัวใจใครบางคนรึเปล่า
  • แล้วเครื่องนี่ยังใช้ได้ไหม (วะ) เนี่ยยยยย

ปกติเราก็มักจะจำกัดขอบเขตของปัญหาใช่ไหม ถ้าเครื่อง Smart Card Reader เจ๊งจริงก็จะได้รู้ไง โดยฝั่ง Linux ก็สามารถใช้ pcsc_scan ตรวจสอบ ผลที่ได้ก็จะประมาณนี้ถ้าทุกอย่างโอเค

ในฝั่ง Windows เองมักใช้โปรแกรมที่ติดมากับ Smart Card Reader ซึ่งปกติก็มักหายไปกับแผ่น Driver เรียบร้อยแล้วหรือใครเพียรพยายามเก็บไว้ก็ดีไป ส่วนเราจะอิ๊อ๊ะอยู่ใย ก็ทำเองเลย โดยความต้องการพื้นฐานสำหรับรันโปรแกรมนี้ คือ

  • .NET Framework 2.0 ขึ้นไป
  • Smart Card Reader
  • การ์ด/บัตร ประชาชนคนไทย 😛

โปรแกรมชื่อ Reader Checker สามารถตรวจสอบว่าเครื่องอ่านหรือบัตรใช้งานได้จริงหรือไม่ วิธีง่าย ๆ ก็ให้โปรแกรมอ่านการ์ด/บัตรนั่นแหล่ะ กรณีที่มีการติดตั้งเครื่องอ่านสมาร์ทการ์ดมากกว่าหนึ่งเครื่องก็สามารถเลือกได้จากลิสต์ ดังรูป

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

ป.ล.

  • โปรแกรมสามารถส่งออก/Export รูปที่อ่านได้ ถ้าต้องการ
  • ไลบรารี่ที่เกี่ยวข้อง กรณีต้องการพัฒนาโปรแกรมที่เกี่ยวกับ บัตรประชาชนคนไทยก็ ตามไปที่ GitHub ของคุณ Chakphanu Komasathit หรือในกลุ่มของ HOSXP
  • Specification ของ PC/SC
  • Windows PC/SC 1.0 (Smart Card)
  • สามารถสนับสนุนค่ากาแฟเราได้นะ Bitcoin Wallet Address :
    3DchASXQrisoqmJfxU6uRsbC5NV3Wsspyb