者 | 阿文
責(zé)編 | 伍杏玲
有時候需要遠(yuǎn)程家里的臺式機(jī)使用,因為我平時都是用 MAC 多,但是遠(yuǎn)程喚醒只能針對局域網(wǎng),比較麻煩,于是我想用微信實現(xiàn)遠(yuǎn)程喚醒機(jī)器。
準(zhǔn)備工作
本程序主要是實現(xiàn)遠(yuǎn)程管理 Windows10操作系統(tǒng)的開機(jī)和關(guān)機(jī):
開機(jī)實現(xiàn)思路
首先通過微信發(fā)送開機(jī)指令,這里我使用的是 itchat 程序會調(diào)用 Paramiko 庫去 SSH 遠(yuǎn)程到內(nèi)網(wǎng)的樹莓派執(zhí)行 WakeOnLan 命令去喚醒 Windows 主機(jī)。
pi@raspberrypi:~ $ wakeonlan -i 192.168.1.0 14:dd:a9:ea:0b:96 Sending magic packet to 192.168.1.0:9 with 14:dd:a9:ea:0b:96
程序會通過 ICMP 協(xié)議, ping 下需要喚醒的目標(biāo)主機(jī)然后進(jìn)行過濾,一個正常的 ICMP 包是64字節(jié),過濾打印出這個64。
例如 ping 百度:
? ~ ping www.baidu.com PING www.a.shifen.com (180.97.33.108): 56 data bytes 64 bytes from 180.97.33.108: icmp_seq=0 ttl=53 time=8.865 ms 64 bytes from 180.97.33.108: icmp_seq=1 ttl=53 time=9.206 ms 64 bytes from 180.97.33.108: icmp_seq=2 ttl=53 time=8.246 ms
用一段 Linux 命令去過濾是否有64,這里為啥要用 head -n 1 呢?
因為有可能會出現(xiàn)2行,經(jīng)過測試,我們只需要取64這個值就可以了:
ping 192.168.1.182 -c 1 | grep 64 | cut -d " " -f 1|head -n 1
如果有則表示開機(jī)成功已經(jīng)聯(lián)網(wǎng)了,返回開機(jī)成功,否則程序繼續(xù)往下走,去喚醒,然后在 ping 一次確認(rèn)是否開機(jī),如果為是則返回開機(jī)成功,否則返回失敗。程序執(zhí)行成功后,在我的網(wǎng)站根目錄創(chuàng)建一個 shutdown 文件,用于后面的關(guān)機(jī)操作:
#!/usr/bin/python # -*- coding: utf-8 -*- import itchat import paramiko import os import time import sys reload(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) def text_reply(msg): if msg['ToUserName'] !='filehelper': return if msg['Text']==u'開機(jī)': paramiko.util.log_to_file('ssh_key-login.log') privatekey=os.path.expanduser(key_file) try: key=paramiko.RSAKey.from_private_key_file(privatekey) except paramiko.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('ping 192.168.1.182 -c 1 | grep 64 | cut -d " " -f 1|head -n 1') sshCheckOpen=stdout.read() sshCheckOpen=sshCheckOpen.strip(' ') print type(sshCheckOpen) print sshCheckOpen #進(jìn)行判斷,如果為64,則說明 ping 成功,說明設(shè)備已經(jīng)在開機(jī)狀態(tài),程序結(jié)束,否則執(zhí)行喚醒 if sshCheckOpen=='64': connect_ok_time=time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) itchat.send(connect_ok_time+u'設(shè)備已經(jīng)開機(jī)', toUserName='filehelper') else: ssh_time=time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) itchat.send(ssh_time+u'開始連接遠(yuǎn)程主機(jī)', toUserName='filehelper') stdin,stdout,stderr=ssh.exec_command('wakeonlan -i 192.168.1.0 14:dd:a9:ea:0b:96') wakeonlan_time=time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) itchat.send(wakeonlan_time+u'執(zhí)行喚醒,等待設(shè)備開機(jī)聯(lián)網(wǎng)', toUserName='filehelper') #由于開機(jī)需要一些時間去啟動網(wǎng)絡(luò),所以這里等等60s time.sleep(60) #執(zhí)行 ping 命令,-c 1 表示只 ping 一下,然后過濾有沒有64,如果有則獲取64傳給sshConStatus stdin,stdout,stderr=ssh.exec_command('ping 192.168.1.182 -c 1 | grep 64 | cut -d " " -f 1|head -n 1') sshConStatus=stdout.read() sshConStatus=sshConStatus.strip(' ') print type(sshConStatus) print sshConStatus #進(jìn)行判斷,如果為64,則說明 ping 成功,設(shè)備已經(jīng)聯(lián)網(wǎng),可以進(jìn)行遠(yuǎn)程連接了,否則發(fā)送失敗消息 if sshConStatus=='64': connect_ok_time=time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) itchat.send(connect_ok_time+u'設(shè)備喚醒成功,您可以遠(yuǎn)程連接了', toUserName='filehelper') else: connect_err_time=time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) itchat.send(connect_err_time+u'設(shè)備喚醒失敗,請檢查設(shè)備是否連接電源', toUserName='filehelper') ssh.close() #在網(wǎng)站根目錄創(chuàng)建一個空文件,命名為 shutdown os.system('touch /www/shutdown') print '執(zhí)行開機(jī)消息成功'
關(guān)機(jī)部分實現(xiàn)
當(dāng)接收關(guān)機(jī)指令時,程序會去刪除網(wǎng)站根目錄的 shutdown 文件,客戶端我寫了幾行代碼,去通過 Requests 庫每隔30s 發(fā)送 HTTP head 請求去判斷文件是否是404,如果是404 這說明文件不存在,調(diào)用系統(tǒng)關(guān)機(jī)操作,執(zhí)行關(guān)機(jī)。
然后 SSH 到樹莓派去 ping 目標(biāo)主機(jī),如果返回為空,則說明關(guān)機(jī)成功,否則關(guān)機(jī)失敗。這只是針對 Windows 的關(guān)機(jī),如果目標(biāo)主機(jī)是 Linux 則簡單多了:
if msg['Text']==u'關(guān)機(jī)': #刪除網(wǎng)站根目錄的shutdown 文件 rmfile=os.system('rm -rf /www/shutdown') if rmfile==0: print '執(zhí)行關(guān)機(jī)消息成功' shutdown_time=time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) itchat.send(shutdown_time+u'正在關(guān)機(jī)....', 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) except paramiko.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'正在確認(rèn)設(shè)備是否完成關(guān)機(jī)操作,大約需要等待60s.', toUserName='filehelper') #等等60秒后確認(rèn),因為關(guān)機(jī)需要一段時間,如果設(shè)置太短,可能網(wǎng)絡(luò)還沒斷開 time.sleep(60) stdin,stdout,stderr=ssh.exec_command('ping 192.168.1.182 -c 1 | grep 64 | cut -d " " -f 1|head -n 1') sshConStatus=stdout.read() sshConStatus=sshConStatus.strip(' ') print type(sshConStatus) print sshConStatus #如果獲取的值為空,則說明已經(jīng)關(guān)機(jī),否則關(guān)機(jī)失敗 if sshConStatus !='64': shutdown_success_err_time=time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) itchat.send(shutdown_success_err_time+u'關(guān)機(jī)成功', toUserName='filehelper') else: shutdown_err_time=time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) itchat.send(shutdown_err_time+u'關(guān)機(jī)失敗,請連接桌面檢查客戶端程序是否正常執(zhí)行', toUserName='filehelper') ssh.close() itchat.auto_login(hotReload=True,enableCmdQR=2) itchat.run()
客戶端代碼,寫完扔計劃任務(wù),開機(jī)啟動:
import requests import os import time while 1: time.sleep(30) r=requests.head("https://awen.me/shutdown") print r.status_code if r.status_code==404: os.system("shutdown -s -t 5")
使用 TeamViewer 連接:
缺點
代碼地址:https://github.com/monkey-wenjun/wchatwakeonlan
文章內(nèi)的代碼如果有 Bug,后續(xù)更新都在 GitHub 上,完整代碼請參考 GitHub ,此文章代碼不再更新。
原文:https://awen.me/post/3709919605.html
聲明:本文為作者投稿,版權(quán)歸對方所有。
SSHFS(SSH Filesystem)是一個基于FUSE的文件系統(tǒng)客戶端,用于通過SSH連接遠(yuǎn)程目錄。SSHFS使用的是SFTP協(xié)議,它是SSH的一個子系統(tǒng),在大多數(shù)SSH服務(wù)器上默認(rèn)啟用
簡介
SSHFS(SSH Filesystem)是一個基于FUSE的文件系統(tǒng)客戶端,用于通過SSH連接遠(yuǎn)程目錄。SSHFS使用的是SFTP協(xié)議,它是SSH的一個子系統(tǒng),在大多數(shù)SSH服務(wù)器上默認(rèn)啟用
與其他網(wǎng)絡(luò)文件系統(tǒng)(如NFS和Samba)相比,SSHFS的優(yōu)勢在于它不需要在服務(wù)器端進(jìn)行任何額外的配置。要使用SSHFS,您只需要SSH訪問遠(yuǎn)程服務(wù)器。
系統(tǒng)環(huán)境
Cetnos7.7
Windows10
安裝
Centos安裝SSHFS
[root@localhost ~]# yum -y install epel-release && yum -y install sshfs
Windows10安裝SSHFS
需要安裝最新版本的WinFsp和SSHFS-Win,
在Centos中掛載遠(yuǎn)程文件系統(tǒng)
SSHFS使用格式:
sshfs [user@]host:[dir] mountpoint [options]
如果沒有指定遠(yuǎn)程目錄,默認(rèn)會連接用戶的家目錄。
例如,遠(yuǎn)程主機(jī)需要訪問root的家目錄,在這里使用root用戶遠(yuǎn)程訪問。掛載點這里使用/mnt文件夾。
[root@localhost ~]# sshfs root@192.168.0.105: /mnt
root@192.168.0.105's password:
系統(tǒng)將提示您輸入用戶密碼。為了避免每次裝載遠(yuǎn)程目錄時鍵入密碼,可以生成SSH密鑰并設(shè)置無密碼登錄。
如果需要開機(jī)自動掛載,可以在/etc/fstab文件中添加:
[root@localhost ~]# echo 'root@192.168.0.105:/Shares /mnt fuse.sshfs defaults 0 0'>> /etc/fstab
前提是需要設(shè)置無密碼登錄,不然開機(jī)不能掛載。
卸載遠(yuǎn)程文件系統(tǒng)
[root@localhost ~]# fusermount -u /mnt/
或者
[root@localhost ~]# umount /mnt
在Windows10中掛載遠(yuǎn)程文件系統(tǒng)
默認(rèn)添加的遠(yuǎn)程目錄是用戶的家目錄。
右鍵此電腦 - 映射網(wǎng)絡(luò)驅(qū)動器
如果需要遠(yuǎn)程掛載根目錄,可以如下操作:
總結(jié)
由于SSHFS使用SSH協(xié)議,所以服務(wù)器和客戶端之間傳輸?shù)乃袛?shù)據(jù)都必須加密和解密。與NFS相比,這會導(dǎo)致性能略有下降,并且客戶端和服務(wù)器上的CPU使用率更高。sshfs可以臨時用來訪問遠(yuǎn)程文件。