เขียน shutdown service ใน ubuntu

ใน ubuntu จะมีโปรแกรมชื่อ systemd  เป็น service manager

ไฟล์ abc.service ต่างๆ จะอยู่ใน  /etc/systemd/system เพื่อให้ service นั้นๆ run ตอนที่คอมเปิดเครื่อง/รีสตาร์ท

ไฟล์ .service ที่เราเขียนเอง จะถูกเก็บไว้เป็น symbolic link ของpathจริง ใน /etc/systemd/system

[Unit]
Description=remote shutdown service

[Service]
ExecStart=/bin/bash -c "python -m uvicorn shutdown_api:app --host 0.0.0.0 --port 7999 --reload"
Restart=always
Type=simple
WorkingDirectory=/mnt/shutdown_api/
RestartSec=10
StandardOutput=syslog
StandardError=syslog

[Install]
WantedBy=multi-user.target

จริงๆแล้ว ใช้ ExecStart=/bin/bash -c “python3.8 /mnt/shutdown_api/shutdown_api.py” ก็น่าจะได้ แต่เซิฟเวอร์ที่ใช้อยู่เป็นอะไรไม่รู้รันคำสั่งธรรมดาไม่ได้ เลยต้องพิมพ์แบบยาวๆ

import uvicorn
from fastapi import FastAPI
import subprocess

app = FastAPI()

@app.get("/")
def shutdown():
    #subprocess.run([f"shutdown -h now"], shell=True)
    password = "serverpassword"
    command = f"echo {password} | sudo -S shutdown -h now"
    print(command)
    subprocess.run(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)    

if __name__ == "__main__":
    uvicorn.run(app, host="0.0.0.0", port=7999, reload=True)

ไฟล์ python นี้คือ ให้ uvicorn server รัน FastAPI application (app)

ส่วน app = FastAPI() ก็จะเรียก def shutdown() ถ้ามี HTTP GET command ถูกเรียกใข้งาน

จากการที่เรา พิมพ์ curl http://192.168.11.122:7999   ใน terminal

ปล.  host=”0.0.0.0″ means that the server will listen on all available network interfaces on the host machine.  This makes the server accessible from any IP address on the network.

วิธีติดตั้ง service

1. sudo systemctl daemon-reload
#to reload the systemd manager configuration

2. sudo systemctl enable shutdown.service
#to enable the service to start at boot (create symbolic link if not exist)

3. sudo systemctl start shutdown.service
#to start the service

4. sudo systemctl status shutdown.service
#to check the status of the service

ถ้า  host=0.0.0.0 ตามที่เขียนไว้ใน python file คือ ok

แต่ถ้าเป็น host=127.0.0.1 คือเป็น loopback จะไม่สามารถเรียก http get จาก คอมเครื่องอื่นในเน็ตเวิคได้

5. netstat -an|more #to check all available services

ปล. เขียนแยกหลายๆ decorator ก็เหมือนจะได้นะ

@app.get(“/shutdown”)
async def shutdown():

@app.get(“/restart”)
async def restart():

ส่วน HTTP POST ดูใช้งานยากอยู่ ยังไม่เคยลอง แต่ประมาณนี้
@app.post(“/items/”)
async def create_item(item: Item):

curl --header "Content-Type: application/json" \
     --request POST \
     --data '{"name": "example item", "price": 9.99}' \
     http://localhost:8000/items/

ตรง –data คือ ส่ง json structure เข้าไปเป็น input ที่ฟังก์ชัน