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

ด้วยความขี้เกียจ เลยคิดว่าเราน่าจะมีอะไรมาเตือนเนอะ ว่า Command นั้นรันเสร็จรึยัง หรือ พังไหม เลยพาลไปนึกถึง Slack ซึ่ง mesodiar เคยเขียนไว้ เรื่อง [Cron] เขียน slackbot ส่ง notification เตือน standup meeting เลยคิดว่าน่าจะเอามาทำอะไรเล่นๆได้เร็วเพราะมีโค้ดมาเลย เอามายำๆ

มาเริ่มกันดีกว่า

เริ่มแรก เราจะสร้าง virtualenv และ virtualenvwrapper มาเพื่อไม่ให้โปรเจ็กของเราไปกระทบกับ python ของเครื่อง และจะได้ง่ายในการจัดการหรือพัฒนาต่อ

$ mkvirtualenv lazy-bot

ลง Slack API ใน virtualenv

(lazy-bot) $ pip install slackclient

สร้าง BOT บน Slack
screen-shot-2560-01-23-at-6-02-24-pm

แอ็ด BOT เราเข้าไปใน Channel ด้วยนะครับ เดียวจะเหวอว่าทำไมข้อความไปมา
จากนั้นเอา API Token มาเก็บไว้ เดียวเราจะเอาไปใส่ในโค้ดของเราครับ

image-uploaded-from-ios-2

 

ตัว Template ของโค้ด ผมหยิบเอามาจาก บล็อก ข้างต้นที่กล่าวไว้

send.py

from slackclient import SlackClient

slack_token = "YOUR_SLACK_API_TOKEN"
slack_client = SlackClient(slack_token)
api_call = slack_client.api_call("channels.list")

if slack_client.rtm_connect():
    print "Successfully connected"
    for channel in api_call.get("channels"):
        if channel.get("name") == "test_server_notificat":
            response = "Your job is done"
            slack_client.api_call("chat.postMessage", channel="test_server_notificat", text=response, as_user=True)
        else:
            print "Connection failed"

ครับ ก็ ง่ายๆครับ

ทดลองด้วยการรัน

python send.py

ข้อความก็จะเข้ามาใน Channel แบบ ชิคๆคูลๆ
screen-shot-2560-01-23-at-10-54-37-pm
โดยเราจะใช้การที่เรารันโปรแกรมของเราแล้วส่งข้อความเนี่ยแหละ มาประยุกต์ใช้กับงานที่ต้องรัน นานๆ

ตอนนี้ผมจะใช้การรันในแบบ

$ sleep 50; python send.py
#หรือ
$ sleep 50 && python send.py

โดยถ้าเป็นแบบนี้ มันจะทำงานแรกให้เสร็จก่อน แล้วค่อยรัน send.py ของเรา

ถ้าอยากให้มันแจ้งคนใน Channel เช่น @here หรือ @channel จะทำได้โดยใส่เป็น tag ดูเพิ่มเติมได้ที่ Basic message formatting ผมใส่ <!here> หรืออ่านว่า ไอ-เฮีย เย้ย!

จากนั้นผมก็เพิ่มให้โปรแกรมของเราสามารถส่งข้อมูล hostname และ IP มาด้วยกะ message เพื่อให้ง่ายต่อการดูข้อความถ้าเราไปรันบนเครื่อง Server

Get Hostname ด้วยการใช้ socket.gethostname()

#ส่วนนี้เป็นการไปเอา Hostname มา
import socket

hostname = socket.gethostname()

Get IP ด้วยการใช้ request.get ไปใช้ API ของเว็บ ipify

from requests import get

ip = get('https://api.ipify.org').text

หรืออาจจะใช้วิธีอื่นที่ไม่ต้อง Call API ทุกครั้งจะทำงานได้เร็วกว่าครับ

จากนั้นเราก็จะต้องนำค่า Hostname กับ IP ที่ได้มาไปรวมเข้ากับ Message ที่เราส่ง

ตอนนี้โค้ดเราจะหน้าตาแบบนี้ครับ

from slackclient import SlackClient
from requests import get
import socket

slack_token = "YOUR_SLACK_API_TOKEN"
slack_client = SlackClient(slack_token)
api_call = slack_client.api_call("channels.list")
hostname = socket.gethostname()
ip = get('https://api.ipify.org').text

if slack_client.rtm_connect():
    print "Successfully connected"
    for channel in api_call.get("channels"):
        if channel.get("name") == "test_server_notificat":
            response = "<!here> Your job on " + hostname + " IP:" + ip + " is done"
            slack_client.api_call("chat.postMessage", channel="test_server_notificat", text=response, as_user=True)
        else:
            print "Connection failed"

จะได้ข้อความาแบบนี้ แถมโดนเด้งเตือนกันทั้ง Channel
image-uploaded-from-ios
image-uploaded-from-ios-1

จริงๆคร่าวๆก็มีประมาณนี้ ที่ได้มาลองเล่น SlackAPI ของ Python แบบขำๆ แต่ทีนี้โปรเจ็กนี้ผมเขียนขึ้นมาหลังจากที่รัน Command ไปแล้ว ก็เลยไปลองหาทริคที่จะโปรแกรมของเราส่งข้อความหลังจาก Process นั้นหายไปโดยจะใช้

watch -g ps -opid -p <PID>; python send.py

ที่มาของคำสั่งนี้จาก superuser.com

คือจะไปดู Process ของเราจาก PID ของ Process โดยดู PID จากวิธีต่างๆเช่นใช้ top หรือ htop ไปดู command ที่รันไปแล้วยังรันค้างอยู่ เป็นต้น

watch เป็นคำสั่งที่ใช้ดู Process ที่รันอยู่แบบเต็มหน้าจอ
-g เป็น Option ของ watch ที่จะออกจาก command เมื่อมี Output เปลี่ยนแปลงไป

หวังว่าโปรเจ็กเล่นๆขำๆของผมจะพอมีประโยขน์สำหรับคนอื่นบ้าง โค้ดนี้ยังพัฒนาต่อให้ใช้งานได้ง่ายกว่านี้เช่นไปทำ executable file ไว้ใน bin จะได้ใช้งานง่ายๆสะดวกกว่านี้ หรือใครมีวิธีที่ง่ายกว่านี้ก็สามารถนำมาเสนอแนะกันได้นะครับผม

(・`ω´・)

Leave a comment

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

%d bloggers like this: