ทดสอบส่ง Line Notify ด้วย curl ใน PowerShell

PowerShell คืออะไร ?

PowerShell is a task automation and configuration management framework from Microsoft, consisting of a command-line shell and associated scripting language. Initially a Windows component only, known as Windows PowerShell, it was made open-source and cross-platform on 18 August 2016 with the introduction of PowerShell Core.[5] The former is built on .NET Framework while the latter on .NET Core.

ที่มา : https://en.wikipedia.org/wiki/PowerShell

ถ้าพูดให้เข้าใจง่าย ๆ คือ เป็น Command Shell รูปใหม่ของ Microsoft ที่คล้ายกับ command line แต่สามารถทำอะไรได้มากกว่า ทำงานบน .NET Framework สามารถจัดการบริหาร Windows ได้ผ่านคำสั่ง cmdlets ทีนี้ถ้าใครคุ้นชินกับ Shell อื่น ๆ ใน Linux หรือ Unix Base ก็จะใช้งานผ่าน Shell อาทิ

  • Bourne shell (sh)
  • Debian Almquist shell (dash)
  • Bourne-Again shell (bash)
  • C shell (csh)

ซึ่ง Shell เหล่านี้มันมี curl ให้ใช้ใน Distro นั้น ๆ อยู่แล้ว (คือติดตั้งมาก่อน ถ้าไม่มีก็ติดตั้งเพิ่มตามแต่ละ Distro ไป) แล้ว curl คืออะไร

curl is a tool to transfer data from or to a server, using one of the supported
protocols (DICT, FILE, FTP, FTPS, GOPHER, HTTP, HTTPS,IMAP, IMAPS, LDAP, LDAPS, POP3,POP3S, RTMP, RTSP, SCP, SFTP, SMB, SMBS, SMTP, SMTPS, TELNET and TFTP).The command is designed to work without user interaction.

ไปตามอ่านวิธีใช้งานกันได้ที่ https://devahoy.com/blog/2016/11/getting-started-with-curl

โดย curl ไม่ได้มีมาพร้อมกับ PowerShell แต่ถ้าเราต้องการใช้คำสั่งนี้ใน PowerShell ที่ให้ผลลัพธ์เช่นเดียวกับ curl หล่ะทำไง ^__^  (มีวิธีติดตั้ง curl ที่เป็นเวอร์ชั่น Windows อยู่แต่ก็นั่นหล่ะ : https://curl.haxx.se/ )

ซึ่ง PowerShell ก็มีคำสั่งที่ใช้งานได้ในลักษณะเดียวกันกับ curl ชื่อว่า Invoke-WebRequest รายละเอียดลึก ๆ ตามไปอ่านที่นี่นะครับ ซึ่ง PowerShell ตั้งแต่เวอร์ชั่น 5.0 เป็นต้นมาสามารถใช้ Alias curl แทน Invoke-WebRequest ได้ ทดสอบก่อนว่าเราใช้ PowerShell เวอร์ชั่นอะไร

$PSversiontable

เกริ่นมาเยอะขิง ๆ อยากแค่ทดสอบ Line Notify เอง ตัดจบหล่ะกันนะ ^___^ มีงานงอก ตามตัวอย่างเอกสารของทางไลน์เวลาเราจะทดสอบส่ง Line Notify สามารถใช้คำสั่งตามนี้

curl -X POST -H 'Authorization: Bearer [access_token]' -F 'message=foobar' https://notify-api.line.me/api/notify

ส่วนใน PowerShell เราทดสอบก่อนว่าสามารถใช้ curl ได้หรือไม่จากคำสั่งนี้

Get-Alias -Definition Invoke-WebRequest | Format-Table -AutoSize

ถ้าขึ้นแบบนี้เป็นอันว่าเราสามารถใช้ curl แทน(Alias) Invoke-WebRequest ได้เลย งั้นก็ทดสอบกันเลย ส่ง Line Notify กัน

curl -Uri 'https://notify-api.line.me/api/notify' -Method Post -Headers @{Authorization = 'Bearer [access_token]'} -Body @{message = 'PowerShell Notification'}

ส่งสำเร็จก็จะขึ้นผลลัพธ์ตามนี้

จบปิ๊ง ^__^ (เราตัดเรื่องการขอ Access Token ไปนะ เชื่อว่าคงหาอ่านได้ไม่ยากก)
ป.ล.1  มือใหม่ PowerShell
ป.ล.2 มือใหม่หัดรัก(หัดเจ็บด้วย)

MySQL ว่าด้วยลำดับและการจัดอันดับข้อมูล

เดิมทีแล้ว MySQL ไม่มีฟังก์ชั่น (Row Number) สำหรับเรียกลำดับที่ (1, 2, 3 …n) ของแถว/เร็คคอร์ดในฐานข้อมูลเหมือนดั่งเช่นเจ้าอื่น ๆ เพราะฉนั้นเหล่านักรบส่วนใหญ่ก็มักสร้างฟังก์ชั่นใส่ลำดับที่แถวเอง

สมมุติเรามีชุดข้อมูลนึงแสดงคะแนนของแต่ละอำเภอ (เอ๊ะ !! คุ้น ๆ ) ตามนี้

CREATE TABLE IF NOT EXISTS `rstanding` (
  `id` int(6) unsigned NOT NULL,
  `name` varchar(20) NOT NULL,
  `score` decimal(10,2) NOT NULL,
  PRIMARY KEY (`id`)
) DEFAULT CHARSET=utf8;
INSERT INTO `rstanding` (`id`, `name`, `score`) VALUES
  ('1', 'A', 98.52),
  ('2', 'B', 97.24),
  ('3', 'C', 96.33),
  ('4', 'E', 96.33),  
  ('5', 'F', 95.02),
  ('6', 'G', 94.88),
  ('7', 'H', 94.88);

การใส่ลำดับที่ของแถวก็จะสร้างฟังก์ชั่นเพื่อนับจำนวนของแถวไปจนสิ้นสุดชุดข้อมูล

SELECT 
    @rownum := @rownum + 1 AS row_number,
    t1.*
FROM rstanding t1, 
(SELECT @rownum := 0) r

จะเห็นได้ว่าคอลัมภ์ row_number เพิ่มขึ้นมาโดยเป็นลำดับที่แถว/เรคคอร์ดนั้น ๆ ในที่นี้เราไม่ได้จัดเรียง (ORDER BY Field [ASC/DESC]) ชุดข้อมูลด้วยคอลัมภ์ใด ๆ

ต่อเนื่องในเรื่องของอันดับ

อันดับ เป็นชื่อของตำแหน่ง ที่มีคำบอกระดับของ ขั้น,ชั้น ที่บ่งบอกถึงความต่างระดับ ซึ่งเป็นผลพวงมาจากผลงานที่มีการประกวดหรือแข่งขัน

การใส่ลำดับที่โดยการจัดเรียงตามคะแนน (คอลัมภ์ score) จากคะแนนสูงสุดไปหาน้อยสุด

ตัวอย่างวิธีที่ 1 ใช้ฟังก์ชั่นเดิมแต่เพิ่มเติมด้วยการใส่เงื่อนไขเพื่อให้จัดลำดับได้

SELECT 
    @rownum := @rownum + 1 AS row_number,
    @ranknum := IF(t1.score < @score, @ranknum + 1, @ranknum) AS row_ranking,    
    t1.*,
@score := t1.score AS dummy
FROM rstanding t1 , (SELECT @score:=0, @rownum:=0, @ranknum :=1) r
ORDER BY t1.score DESC

ผลลัพธ์การจัดเรียงก็จะได้ตามนี้

จากผลลัพธ์ที่ได้ในวิธีที่ 1 เราสามารถกรองได้ว่าเราสนใจลำดับที่ได้ลำดับอะไรบ้าง เช่นต้องการทราบว่าคนที่ได้ลำดับที่ 3 มีใครบ้างก็สามารถกรองได้จากคอลัมภ์ WHERE row_ranking = ?

SELECT
    t2.*
FROM (
  SELECT 
      @rownum := @rownum + 1 AS row_number,
      @ranknum := IF(t1.score < @score, 		
      @ranknum + 1, @ranknum) AS row_ranking,    
      t1.*,
      @score := t1.score AS dummy
  FROM rstanding t1 , (SELECT @score:=0, @rownum:=0, @ranknum :=1) r
  ORDER BY t1.score DESC
) t2 
WHERE t2.row_ranking = 3

ตัวอย่างวิธีที่ 2 กรณีที่สนใจลำดับที่นั้น ๆ ก็นับจำนวน (แบบไม่ซ้ำ) ในลำดับก่อนหน้า เช่น สนใจลำดับที่ 3 ลำดับก่อนหน้าคือ 2 ลำดับ

SELECT
    t1.*
FROM rstanding t1
WHERE 2 = (SELECT COUNT(DISTINCT t2.score) FROM rstanding t2 WHERE t1.score < t2.score)

ตัวอย่างวิธีที่ 3 หาจำนวน LIMIT LIMIT offset, count;

SELECT
    t1.*
FROM rstanding t1
WHERE t1.score = (SELECT t2.score FROM rstanding t2 ORDER BY t2.score DESC LIMIT 3,1);

ตัวอย่างวิธีที่ 4 ทุกอย่างง่ายขึ้น MySQL เห็นคงเห็นว่าจะทำให้ยุ่งยากไปใยเล่า เรามีฟังก์ชั่นให้ใช้นะ แต่ช้าก่อน มันมีในเวอร์ชั่น 8 เป็นต้นไปนะจ๊ะ เวอร์ชั่นก่อนหน้าก็อด

ROW_NUMBER() Number of current row within its partition
DENSE_RANK() Rank of current row within its partition, without gaps
RANK() Rank of current row within its partition, with gaps

ดูวิธีการใช้งานกันเลย

WITH ranked_score AS (
  SELECT 
      ROW_NUMBER() OVER (ORDER BY score DESC) rownum,
      RANK() OVER (ORDER BY score DESC) row_ranking,
      DENSE_RANK() OVER (ORDER BY score DESC) drow_ranking,
      id,
      name,
      score
  FROM rstanding
)
SELECT * FROM ranked_score; -- WHERE drow_ranking = 3;

ผลลัพธ์กรณีที่เราไม่กรองใด ๆ ก็จะแสดงผลดังนี้

จบปิ๊ง ^_^
#แด่ตัวสำรองอันดับหนึ่ง

ป.ล.

 

MySQL แสดงผลวันที่แบบไทย (แบบเต็มและแบบย่อ)

การแสดงผลวัน เดือน ปี ของ MySQL จะแสดงผลเป็นวันที่ในรูปแบบสากลคือในรูปแบบภาษาอังกฤษจะแบบเต็มหรือแบบย่อก็ยังเป็นภาษาอังกฤษอยู่ดี ซึ่งในภาษาอื่นก็ยังไม่รองรับการแสดงผลในภาษาท้องถิ่นนั้น ๆ (รวมทั้งฟังก์ชั่นที่สามารถใช้งานด้วย)

ในกรณีที่ต้องการแสดงผล วัน เดือน ปี เป็นภาษาไทยจึงจำเป็นต้องสร้างฟังก์ชั่นขึ้นมาใช้งานเองซึ่งเราจะมาเขียนฟังก์ชั่นนี้กันโดยอาศัยฟังก์ชั่นของ MySQL ที่ชื่อว่า SUBSTRING_INDEX()

Return a substring of a string before a specified number of delimiter occurs
Syntax
SUBSTRING_INDEX(string, delimiter, number)
Parameter Values

string	Required. The original string
delimiter	Required. The delimiter to search for
number	Required. The number of times to search for the delimiter. Can be both a positive or negative number. If it is a positive number, this function returns all to the left of the delimiter. If it is a negative number, this function returns all to the right of the delimiter.

ตัวอย่างการใช้งาน

การใช่งานฟังก์ชั่นจาก w3resource.com

การใช่งานฟังก์ชั่นจาก w3resource.com

จะเห็นได้ว่าเราสามารถนำมาสร้างชุดคำสั่งใน MySQL สำหรับการแสดงผลวันที่แบบไทยทั้งแบบเต็มและแบบย่อ (วัน x ที่ x เดือน xxxx พ.ศ. xxxx) โดย

กำหนดค่าคงที่รายชื่อเดือนและชื่อวันในภาษาไทย

-- กำหนดค่าคงที่รายชื่อเดือนและชื่อวันในภาษาไทย
SET @monthname_long_th = 'มกราคม,กุมภาพันธ์,มีนาคม,เมษายน,พฤษภาคม,มิถุนายน,กรกฎาคม,สิงหาคม,กันยายน,ตุลาคม,พฤศจิกายน,ธันวาคม';
SET @dayname_long_th = 'อาทิตย์,จันทร์,อังคาร,พุธ,พฤหัสบดี,ศุกร์,เสาร์';

ใช้ฟังก์ชั่นใน MySQL เพื่อดึงค่าวันที่ วันในสัปดาห์ เดือน และปี

-- ใช้ฟังก์ชั่นใน MySQL เพื่อดึงค่าวันที่ วันในสัปดาห์ เดือน และปี 
SET @d = DAY(CURDATE()); 
SET @dddd = SUBSTRING_INDEX(SUBSTRING_INDEX(@dayname_long_th, ',', DAYOFWEEK(CURDATE())), ',' , -1); 
SET @mmmm = SUBSTRING_INDEX(SUBSTRING_INDEX(@monthname_long_th, ',', MONTH(CURDATE())), ',' , -1); 
SET @yyyy = YEAR(CURDATE()) + 543;

ทดสอบผลลัพธ์ที่ได้

SELECT CONCAT_WS(' ', 'วัน', @dddd, 'ที่', @d, 'เดือน', @mmmm, 'พ.ศ.', @yyyy);
-- วัน เสาร์ ที่ 27 เดือน กรกฎาคม พ.ศ. 2562

จบปิ๊ง ^__^ (ลองไปปรับเป็นฟังก์ชั่นรวมทั้งแบบย่อกันดู)
ตามไปทดลองกันได้ที่

MySQL generates a sequence of numeric values

หลังจากได้อ่านและลอง Sequence ใน MariaDB 10.3 แล้ว มันช่างง่ายเหลือเกินให้ตายเถอะโรบิน (แนะนำให้ไปอ่านยังไงก็ได้ใช้แน่ ๆ ) แต่บล๊อกนี้เราจะไม่ได้เขียนเรื่องนี้ 5555 เราจะใช้วิธีที่เรียกว่า CTE (Common Table Expression) สำหรับการสร้างชุดข้อมูล CTE ซึ่งเริ่มใช้ได้ใน MySQL 8.0, MariaDB 10.2 เป็นต้นมาซึ่งเอาจริง ๆ ก็ง่ายพอ ๆ กันแหล่ะ เราเคยเขียนในบทความเก่า ๆ ลองไปหาอ่านกันได้ หรือของ อ.ประเสริฐ

ลักษณของ CTE ใช้การเรียกโดยวิธี Recursive รูปแบบใน MySQL จะเป็นแบบนี้

with_clause:
    WITH [RECURSIVE]
        cte_name [(col_name [, col_name] ...)] AS (subquery)
        [, cte_name [(col_name [, col_name] ...)] AS (subquery)] ...

ลักษณะของคำสั่งนี้คือ

สมมุติเรามีโจทย์ตามข้างต้น คือการสร้างตารางชั่วคราวที่เก็บ sequence number จาก 1 ถึง 100 เราก็เขียนได้ดังนี้

WITH RECURSIVE numbers AS (
    SELECT 1 AS value
    UNION ALL
    SELECT value + 1 AS value
    FROM numbers
    WHERE numbers.value < 100
)
SELECT *
FROM numbers;

ผลลัพธ์ก็ตามนี้ ดูได้ใน dbfiddle

สั้น ๆ และง่ายใช่ไหม อ่านจบตามไปอ่าน  sequence ต่อ แนะนำเลย
หลับฝันดีมีแฮง ^__^

(My) Wishlist WordPress Starter Themes

ถ้าอยากสร้าง WordPress Theme เองควรเริ่มจากอะไรดี ? คำถามก็สั้นๆ รวมถึงเวลาด้วย เพราะงั้นก็ควรเริ่มที่ Starter Theme นั่นแหล่ะง่ายและเร็วสุดแล้ว แล้วจะเลือกตัวไหนดีหล่ะ เรามีตัวเลือกมาให้คร่าว ๆ ซึ่งบางธีมเองก็เวอร์ชั่นเก่าพอสมควรแต่โครงสร้างมันง่ายสำหรับการแก้ไขและทำเพิ่ม (เรียงตามตัวอักษรหล่ะกัน)

ป.ล. บล๊อกสั้น ๆ นะ พยายามบังคับตัวเองให้บล๊อกอยู่

  1. Aamla
  2. Air-light
  3. Beans
  4. Bootstrap-four
  5. FoundationPress
  6. Generic
  7. html5blank
  8. JointsWP
  9. Nebula
  10. Oceanwp
  11. _s
  12. Quark
  13. Silencio
  14. _tk
  15. WP-bootstrap-starter
  16. WP-Rootstrap
  17. Understrap
  18. twentynineteen
    twentyseventeen
    twentysixteen

 

Unfri(end)

เก็บรักที่เพิ่งพ้นไป
เก็บใจที่เพิ่งพ้นมา
บอกลาแล้ววันเก่า
เหลือแค่เพียงน้ำตา
กับแผลที่เธอให้มา

— ช่วงที่เศร้าที่สุดในเพลงกลับเป็น 24 วินาทีแรก

Create multiple directories at once mkdir

สั้น !!
ความน่ารักและมีประโยชน์ของ Bash ก็คือบางอย่างเราก็สามารถลดเวลาได้ด้วยการทำ Script สั้น ๆ เช่นกรณีนี้ ต้องการสร้าง Directory ตามโครงสร้างนี้

├── config
│   └── webui
├── data
│   ├── director
│   ├── storage
│   └── webui
├── mysql
│   ├── data
│   └── log

เราสามารถใช้คำสั่งสั้น ๆ ข้างล่าง เพื่อสร้างโฟลเดอร์

mkdir -p {data/{director,storage,webui},config/webui,mysql/{data,log}}

และกรณีอื่น ๆ อีก ไปลองกันได้ว่าผลลัพธ์จะได้ออกมายังไง

mkdir test{1..50}
mkdir -p test{1..50}/sub{1..50}
mkdir {a-z}12345 
mkdir {1,2,3}
mkdir test{01..10}
mkdir -p `date '+%y%m%d'`/{1,2,3} 
mkdir -p $USER/{1,2,3}

จบปิ๊ง !!

Optimize คำสั่ง SQL สำหรับการสุ่มเวชระเบียนด้วยวิธี Systematic sampling

เดิมเคยเขียนคำสั่ง SQL ไว้นานละพอแก่ตัวขึ้นกลับไปดู มันก็สมควรเปลี่ยน (Optimize) แหล่ะ  เราจะไม่ลงรายละเอียดเรื่องของการตรวจสอบเวชระเบียนหล่ะกัน ขอข้ามไปพาร์ทสำหรับการเตรียมข้อมูล (กลุ่มตัวอย่าง) เพื่อให้ผู้เกี่ยวข้องทำงานต่อ
เริ่มด้วย Systematic Random Sampling (การสุ่มตัวอย่างแบบเป็นระบบ)

การสุ่มตัวอย่างแบบเป็นระบบ ( Systematic sampling) เป็นการสุ่มตัวอย่างโดยมีรายชื่อของทุกหน่วยประชากรมาเรียงเป็นระบบตามบัญชีเรียกชื่อ การสุ่มจะแบ่งประชากรออกเป็นช่วงๆที่เท่ากันอาจใช้ช่วงจากสัดส่วนของขนาดกลุ่มตัวอย่างและประชากร แล้วสุ่มประชากรหน่วยแรก ส่วนหน่วยต่อๆไปนับจากช่วงสัดส่วนที่คำนวณไว้

ขั้นตอนคร่าว ๆ ของการเตรียมข้อมูลสุ่มตัวอย่างแบบนี้คือ

  1. เลือกแฟ้มจาก OPD Card หรือ สมุดทะเบียนผู้มารับบริการ จำแนกตาม PID หรือ HN หรือวันที่ที่มารับบริการ
  2. หาช่วง Interval (I) ของการสุ่มโดยใช้สูตร
    I = จำนวนเวชระเบียนผู้ป่วยทั้งหมด ÷ จำนวนเวชระเบียนผู้ป่วยที่ต้องการ
  3. หาค่าตั้งต้นโดยการจับฉลาก (สุ่ม) เช่น จับฉลากได้หมายเลข 5 ให้เลือกเวชระเบียนแฟ้มแรกคือลำดับที่ 5 แล้วนับต่อไปทุกลำดับที่ I เช่นกรณีได้ค่า I = 3 ก็นับไปเลย 5, 8, 11, 14, 17, 20, ………จนได้ครบตามจำนวนที่ต้องการ

มาดู SQL ตัวที่พยายาม  Optimize กัน

 

Implements a scheduled task using Supercronic

Cron เป็นโปรแกรมสำหรับการทำ schedule tasks  ที่เราต้องการ พบเจอได้ใน Unix-like OS ตามไปอ่านรายละเอียดได้ที่นี่

Supercronic ก็จัดอยู่ในโปรแกรมข้างต้น คนทำให้นิยามว่า

Supercronic is a crontab-compatible job runner, designed specifically to run in containers.

เหตุผลที่ทำ Supercronic ขึ้นมาตามไปอ่านรายละเอียดได้ที่นี่ (ไม่ได้ขี้เกียจนะ 55+) ที่นี้เราลองมาอิมพลีเมนท์กันดู

เริ่มก็สร้าง Dockerfile ตามนี้

FROM alpine:3.8
LABEL author="mf"
LABEL version="latest"

ENV SUPERCRONIC_VERSION="v0.1.6" \
    SUPERCRONIC_PACKAGE=supercronic-linux-amd64 \
    SUPERCRONIC_SHA1SUM=c3b78d342e5413ad39092fd3cfc083a85f5e2b75

ENV SUPERCRONIC_URL=https://github.com/aptible/supercronic/releases/download/$SUPERCRONIC_VERSION/$SUPERCRONIC_PACKAGE

ENV TZ Asia/Bangkok

# install dependencies
RUN apk add --update --no-cache ca-certificates curl \
# install supercronic
    && curl -fsSLO "$SUPERCRONIC_URL" \
    && echo "${SUPERCRONIC_SHA1SUM}  ${SUPERCRONIC_PACKAGE}" | sha1sum -c - \
    && chmod +x "${SUPERCRONIC_PACKAGE}" \
    && mv "${SUPERCRONIC_PACKAGE}" "/bin/${SUPERCRONIC_PACKAGE}" \
    && ln -s "/bin/${SUPERCRONIC_PACKAGE}" /bin/supercronic \
# remove unwanted deps & cleanup
    && apk del --purge ca-certificates curl \
    && rm -rf /tmp/* /var/cache/apk/*

ADD crontab.sample /etc/crontab
RUN chmod 0644 /etc/crontab

ENTRYPOINT ["supercronic"]
CMD ["/etc/crontab"]

** ณ ตอนนี้ (29 พ.ย. 61) เวอร์ชั่นล่าสุดอยู่ที่ 0.1.6 ลองเช็คดูเรื่อย ๆ ที่ Github

ตามด้วยการสร้างไฟล์ Crontab สำหรับทำงาน ตัวอย่าง คือกำหนดให้แสดงผลคำว่า “hello from Supercronic” ทุก 1 นาที

# Run every minute
*/1 * * * * echo "hello from Supercronic"

เสร็จก็ทำการ Build และรัน container sudo docker build -t mf/supercronic . && sudo docker run -it mf/supercronicผลลัพธ์จะได้ตามนี้

จบปิ๊ง ^__^

Source

  • https://github.com/aptible/supercronic

Disable screen sleep on Raspberry PI

Raspberry PI เวลาเอามาใช้ทำตัว Dashboard หรือ Kiosk สักพักก็จะเข้าสู่ Sleep mode วิธีการแก้ไข ก็คือให้ทำการแก้ไขไฟล์ lightdm.conf

sudo nano /etc/lightdm/lightdm.conf

เพิ่มบรรทัดนี้เข้าไปในเซคชั่น [Seat:*]

xserver-command=X -s 0 dpms

เสร็จก็ Reboot รอบนึง จบปิ๊งงง ^__^