有時候需要遠程家里的臺式機使用,因為我平時都是用 MAC 多,但是遠程喚醒只能針對局域網(wǎng),比較麻煩,于是我想用微信實現(xiàn)遠程喚醒機器。
準備工作
本程序主要是實現(xiàn)遠程管理 Windows10操作系統(tǒng)的開機和關機:
在 Windows機器的相同內(nèi)網(wǎng)中放一個 Linux 主機,我這里用樹莓派代替,如果你是用 OpenWrt 之類的路由器也可以。
Linux 主機需要能夠遠程訪問,我這里是有 FRP 將樹莓派的端口映射到我的公網(wǎng) Linux 主機上。所以可以隨時遠程 SSH 過去。
Windows 機器的網(wǎng)卡必須是有線連接,支持網(wǎng)絡喚醒功能。
開機實現(xiàn)思路
首先通過微信發(fā)送開機指令,這里我使用的是 itchat 程序會調(diào)用 Paramiko 庫去 SSH 遠程到內(nèi)網(wǎng)的樹莓派執(zhí)行 WakeOnLan 命令去喚醒 Windows 主機。
pi@raspberrypi:~$wakeonlan-i192.168.1.014:dd:a9:ea:0b:96Sendingmagicpacketto192.168.1.0:9with14:dd:a9:ea:0b:96
程序會通過 ICMP 協(xié)議, ping 下需要喚醒的目標主機然后進行過濾,一個正常的 ICMP 包是64字節(jié),過濾打印出這個64。
例如 ping 百度:
?~pingwww.baidu.comPINGwww.a.shifen.com(180.97.33.108):56databytes64bytesfrom180.97.33.108:icmp_seq=0ttl=53time=8.865ms64bytesfrom180.97.33.108:icmp_seq=1ttl=53time=9.206ms64bytesfrom180.97.33.108:icmp_seq=2ttl=53time=8.246ms
用一段 Linux 命令去過濾是否有64,這里為啥要用 head -n 1 呢?
因為有可能會出現(xiàn)2行,經(jīng)過測試,我們只需要取64這個值就可以了:
ping192.168.1.182-c1|grep64|cut-d""-f1|head-n1
如果有則表示開機成功已經(jīng)聯(lián)網(wǎng)了,返回開機成功,否則程序繼續(xù)往下走,去喚醒,然后在 ping 一次確認是否開機,如果為是則返回開機成功,否則返回失敗。程序執(zhí)行成功后,在我的網(wǎng)站根目錄創(chuàng)建一個 shutdown 文件,用于后面的關機操作:
#!/usr/bin/python#-*-coding:utf-8-*-importitchatimportparamikoimportosimporttimeimportsysreload(sys)sys.setdefaultencoding('utf-8')hostname=''username=''port=key_file='/home/fangwenjun/.ssh/id_rsa'filename='/home/fangwenjun/.ssh/known_hosts'@itchat.msg_register(itchat.content.TEXT)deftext_reply(msg):ifmsg['ToUserName']!='filehelper':returnifmsg['Text']==u'開機':paramiko.util.log_to_file('ssh_key-login.log')privatekey=os.path.expanduser(key_file)try:key=paramiko.RSAKey.from_private_key_file(privatekey)exceptparamiko.PasswordRequiredException:key=paramiko.RSAKey.from_private_key_file(privatekey,key_file_pwd)ssh=paramiko.SSHClient()ssh.load_system_host_keys(filename=filename)ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())ssh.connect(hostname=hostname,username=username,pkey=key,port=port)#執(zhí)行喚醒命令stdin,stdout,stderr=ssh.exec_command('ping192.168.1.182-c1|grep64|cut-d""-f1|head-n1')sshCheckOpen=stdout.read()sshCheckOpen=sshCheckOpen.strip(' ')printtype(sshCheckOpen)printsshCheckOpen#進行判斷,如果為64,則說明ping成功,說明設備已經(jīng)在開機狀態(tài),程序結束,否則執(zhí)行喚醒ifsshCheckOpen=='64':connect_ok_time=time.strftime("%Y-%m-%d%H:%M:%S",time.localtime())itchat.send(connect_ok_time+u'設備已經(jīng)開機',toUserName='filehelper')else:ssh_time=time.strftime("%Y-%m-%d%H:%M:%S",time.localtime())itchat.send(ssh_time+u'開始連接遠程主機',toUserName='filehelper')stdin,stdout,stderr=ssh.exec_command('wakeonlan-i192.168.1.014:dd:a9:ea:0b:96')wakeonlan_time=time.strftime("%Y-%m-%d%H:%M:%S",time.localtime())itchat.send(wakeonlan_time+u'執(zhí)行喚醒,等待設備開機聯(lián)網(wǎng)',toUserName='filehelper')#由于開機需要一些時間去啟動網(wǎng)絡,所以這里等等60stime.sleep(60)#執(zhí)行ping命令,-c1表示只ping一下,然后過濾有沒有64,如果有則獲取64傳給sshConStatusstdin,stdout,stderr=ssh.exec_command('ping192.168.1.182-c1|grep64|cut-d""-f1|head-n1')sshConStatus=stdout.read()sshConStatus=sshConStatus.strip(' ')printtype(sshConStatus)printsshConStatus#進行判斷,如果為64,則說明ping成功,設備已經(jīng)聯(lián)網(wǎng),可以進行遠程連接了,否則發(fā)送失敗消息ifsshConStatus=='64':connect_ok_time=time.strftime("%Y-%m-%d%H:%M:%S",time.localtime())itchat.send(connect_ok_time+u'設備喚醒成功,您可以遠程連接了',toUserName='filehelper')else:connect_err_time=time.strftime("%Y-%m-%d%H:%M:%S",time.localtime())itchat.send(connect_err_time+u'設備喚醒失敗,請檢查設備是否連接電源',toUserName='filehelper')ssh.close()#在網(wǎng)站根目錄創(chuàng)建一個空文件,命名為shutdownos.system('touch/www/shutdown')print'執(zhí)行開機消息成功'
關機部分實現(xiàn)
當接收關機指令時,程序會去刪除網(wǎng)站根目錄的 shutdown 文件,客戶端我寫了幾行代碼,去通過 Requests 庫每隔30s 發(fā)送 HTTP head 請求去判斷文件是否是404,如果是404 這說明文件不存在,調(diào)用系統(tǒng)關機操作,執(zhí)行關機。
然后 SSH 到樹莓派去 ping 目標主機,如果返回為空,則說明關機成功,否則關機失敗。這只是針對 Windows 的關機,如果目標主機是 Linux 則簡單多了:
ifmsg['Text']==u'關機':#刪除網(wǎng)站根目錄的shutdown文件rmfile=os.system('rm-rf/www/shutdown')ifrmfile==0:print'執(zhí)行關機消息成功'shutdown_time=time.strftime("%Y-%m-%d%H:%M:%S",time.localtime())itchat.send(shutdown_time+u'正在關機....',toUserName='filehelper')paramiko.util.log_to_file('ssh_key-login.log')privatekey=os.path.expanduser(key_file)try:key=paramiko.RSAKey.from_private_key_file(privatekey)exceptparamiko.PasswordRequiredException:key=paramiko.RSAKey.from_private_key_file(privatekey,key_file_pwd)ssh=paramiko.SSHClient()ssh.load_system_host_keys(filename=filename)ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())ssh.connect(hostname=hostname,username=username,pkey=key,port=port)itchat.send(shutdown_time+u'正在確認設備是否完成關機操作,大約需要等待60s.',toUserName='filehelper')#等等60秒后確認,因為關機需要一段時間,如果設置太短,可能網(wǎng)絡還沒斷開time.sleep(60)stdin,stdout,stderr=ssh.exec_command('ping192.168.1.182-c1|grep64|cut-d""-f1|head-n1')sshConStatus=stdout.read()sshConStatus=sshConStatus.strip(' ')printtype(sshConStatus)printsshConStatus#如果獲取的值為空,則說明已經(jīng)關機,否則關機失敗ifsshConStatus!='64':shutdown_success_err_time=time.strftime("%Y-%m-%d%H:%M:%S",time.localtime())itchat.send(shutdown_success_err_time+u'關機成功',toUserName='filehelper')else:shutdown_err_time=time.strftime("%Y-%m-%d%H:%M:%S",time.localtime())itchat.send(shutdown_err_time+u'關機失敗,請連接桌面檢查客戶端程序是否正常執(zhí)行',toUserName='filehelper')ssh.close()itchat.auto_login(hotReload=True,enableCmdQR=2)itchat.run()
客戶端代碼,寫完扔計劃任務,開機啟動:
importrequestsimportosimporttimewhile1:time.sleep(30)r=requests.head("https://awen.me/shutdown")printr.status_codeifr.status_code==404:os.system("shutdown-s-t5")
使用 TeamViewer 連接:
缺點
網(wǎng)頁端微信必須一直登錄,不方便,這個就需要微信不能斷網(wǎng)了。
WakeOnLan 是廣播 MAC 地址的,貌似不能返回是否成功沒,所以還是要 ping 主機看看通不通,判斷下。
需要一個樹莓派做跳板機,否則也不能喚醒內(nèi)網(wǎng)設備。
如果只允許自己控制最好是使用文件助手來發(fā)送消息,因為默認情況下,任何人都可以給你發(fā)送指令開機。
Windows需要安裝TeamViewer并且設置為開機自動啟動以及綁定賬號設置無人值守模式。這樣方便遠程,如果是Linux 則不需要開啟 ssh 就可以了。
代碼地址:https://github.com/monkey-wenjun/wchatwakeonlan
文章內(nèi)的代碼如果有 Bug,后續(xù)更新都在 GitHub 上,完整代碼請參考 GitHub ,此文章代碼不再更新。
原文:https://awen.me/post/3709919605.html
-
WINDOWS
+關注
關注
3文章
3545瀏覽量
88693 -
路由器
+關注
關注
22文章
3732瀏覽量
113776 -
python
+關注
關注
56文章
4797瀏覽量
84687
原文標題:在家想遠程公司電腦?Python +微信一鍵連接
文章出處:【微信號:rgznai100,微信公眾號:rgznai100】歡迎添加關注!文章轉載請注明出處。
發(fā)布評論請先 登錄
相關推薦
評論