作者 | 阿文

转载自 CSDN(ID:CSDNnews)

有时候需要远程家里的台式机使用,因为我平时都是用 MAC 多,但是远程唤醒只能针对局域网,比较麻烦,于是我想用微信实现远程唤醒机器。

准备工作

本程序主要是实现远程管理 Windows10操作系统的开机和关机:

  1. 在 Windows机器的相同内网中放一个 Linux 主机,我这里用树莓派代替,如果你是用 OpenWrt 之类的路由器也可以。

  2. Linux 主机需要能够远程访问,我这里是有 FRP 将树莓派的端口映射到我的公网 Linux 主机上。所以可以随时远程 SSH 过去。

  3. Windows 机器的网卡必须是有线连接,支持网络唤醒功能。

开机实现思路

首先通过微信发送开机指令,这里我使用的是 itchat 程序会调用 Paramiko 库去 SSH 远程到内网的树莓派执行 WakeOnLan 命令去唤醒 Windows 主机。

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 协议, ping 下需要唤醒的目标主机然后进行过滤,一个正常的 ICMP 包是64字节,过滤打印出这个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 呢?

因为有可能会出现2行,经过测试,我们只需要取64这个值就可以了:

ping 192.168.1.182 -c 1 | grep 64 | cut -d " " -f 1|head -n 1

如果有则表示开机成功已经联网了,返回开机成功,否则程序继续往下走,去唤醒,然后在 ping 一次确认是否开机,如果为是则返回开机成功,否则返回失败。程序执行成功后,在我的网站根目录创建一个 shutdown 文件,用于后面的关机操作:

#!/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'开机':
        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)
        #执行唤醒命令
        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
        #进行判断,如果为64,则说明 ping 成功,说明设备已经在开机状态,程序结束,否则执行唤醒
        if sshCheckOpen == '64':
            connect_ok_time = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) 
            itchat.send(connect_ok_time+u'设备已经开机', 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 -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'执行唤醒,等待设备开机联网', toUserName='filehelper')
            #由于开机需要一些时间去启动网络,所以这里等等60s    
            time.sleep(60)
            #执行 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
            #进行判断,如果为64,则说明 ping 成功,设备已经联网,可以进行远程连接了,否则发送失败消息
            if sshConStatus == '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()
            #在网站根目录创建一个空文件,命名为 shutdown
            os.system('touch /www/shutdown')
            print '执行开机消息成功'

关机部分实现

当接收关机指令时,程序会去删除网站根目录的 shutdown 文件,客户端我写了几行代码,去通过 Requests 库每隔30s 发送 HTTP head 请求去判断文件是否是404,如果是404 这说明文件不存在,调用系统关机操作,执行关机。

然后 SSH 到树莓派去 ping 目标主机,如果返回为空,则说明关机成功,否则关机失败。这只是针对 Windows 的关机,如果目标主机是 Linux 则简单多了:

if msg['Text'] ==  u'关机':
        #删除网站根目录的shutdown 文件
        rmfile = os.system('rm -rf /www/shutdown')
        if rmfile == 0:
            print '执行关机消息成功'
        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)
        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'正在确认设备是否完成关机操作,大约需要等待60s.', toUserName='filehelper')
        #等等60秒后确认,因为关机需要一段时间,如果设置太短,可能网络还没断开
        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
        #如果获取的值为空,则说明已经关机,否则关机失败
        if sshConStatus != '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'关机失败,请连接桌面检查客户端程序是否正常执行', toUserName='filehelper')
        ssh.close()
itchat.auto_login(hotReload=True,enableCmdQR=2)
itchat.run()

客户端代码,写完扔计划任务,开机启动:

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 连接:

缺点

  1. 网页端微信必须一直登录,不方便,这个就需要微信不能断网了。

  2. WakeOnLan 是广播 MAC 地址的,貌似不能返回是否成功没,所以还是要 ping 主机看看通不通,判断下。

  3. 需要一个树莓派做跳板机,否则也不能唤醒内网设备。

  4. 如果只允许自己控制最好是使用文件助手来发送消息,因为默认情况下,任何人都可以给你发送指令开机。

  5. Windows需要安装TeamViewer并且设置为开机自动启动以及绑定账号设置无人值守模式。这样方便远程,如果是Linux 则不需要开启 ssh 就可以了。

代码地址:https://github.com/monkey-wenjun/wchatwakeonlan

文章内的代码如果有 Bug,后续更新都在 GitHub 上,完整代码请参考 GitHub ,此文章代码不再更新。

原文:https://awen.me/post/3709919605.html

(本文为AI科技大本营转载文章,转载请微信联系原作者)

群招募

扫码添加小助手微信,回复:公司+研究方向(学校+研究方向),邀你加入技术交流群。技术群审核较严,敬请谅解。

推荐阅读:

  • 优秀开发者必备技能包:Python调试器

  • 十大经典排序算法动画与解析,看我就够了

  • 访问量最高超7百万的Stack Overflow问题竟然是...

  • 新鲜开源:基于TF2.0的深度强化学习平台

  • 交易机器人春天已来?先看完这篇再说吧

  • 程序员求职新思路:互联网巨鳄瓜分 ToB 资源全公开

  • 移动开发还有未来吗?

  • 全面剖析企业私有云

  • 月入5万,程序员夫人们过上"贵妇"生活了吗?

点击“阅读原文”,查看历史精彩文章。

在家想远程公司电脑?Python +微信一键连接相关推荐

  1. 在家想远程公司电脑?Python + 微信一键连接!

    作者 | 阿文 责编 | 伍杏玲 有时候需要远程家里的台式机使用,因为我平时都是用 MAC 多,但是远程唤醒只能针对局域网,比较麻烦,于是我想用微信实现远程唤醒机器. 快速挑战Python全栈工程师: ...

  2. 在家想远程公司电脑?Python+微信一键连接!

    作者 | 阿文 责编 | 伍杏玲 有时候需要远程家里的台式机使用,因为我平时都是用 MAC 多,但是远程唤醒只能针对局域网,比较麻烦,于是我想用微信实现远程唤醒机器. 准备工作 本程序主要是实现远程管 ...

  3. python远程安装软件_在家想远程公司电脑?Python + 微信一键连接!

    作者 | 阿文 责编 | 伍杏玲 有时候需要远程家里的台式机使用,因为我平时都是用 MAC 多,但是远程唤醒只能针对局域网,比较麻烦,于是我想用微信实现远程唤醒机器. 准备工作 本程序主要是实现远程管 ...

  4. python 执行ping命令_Python黑科技:在家远程遥控公司电脑,python+微信一键连接!...

    有时候需要远程家里的台式机使用,因为我平时都是用 MAC 多,但是远程唤醒只能针对局域网,比较麻烦,于是我想用微信实现远程唤醒机器. 准备工作 本程序主要是实现远程管理 Windows10操作系统的开 ...

  5. Python黑科技:在家远程遥控公司电脑,python+微信一键连接!

    有时候需要远程家里的台式机使用,因为我平时都是用 MAC 多,但是远程唤醒只能针对局域网,比较麻烦,于是我想用微信实现远程唤醒机器. *注意:全文代码可左右滑动查看 准备工作 本程序主要是实现远程管理 ...

  6. 远程连接电脑_Python黑科技:在家远程遥控公司电脑,python+微信一键连接!

    有时候需要远程家里的台式机使用,因为我平时都是用 MAC 多,但是远程唤醒只能针对局域网,比较麻烦,于是我想用微信实现远程唤醒机器. 准备工作 本程序主要是实现远程管理 Windows10操作系统的开 ...

  7. 远程唤醒_Python黑科技:在家远程遥控公司电脑,python+微信一键连接!

    有时候需要远程家里的台式机使用,因为我平时都是用 MAC 多,但是远程唤醒只能针对局域网,比较麻烦,于是我想用微信实现远程唤醒机器. 准备工作 本程序主要是实现远程管理 Windows10操作系统的开 ...

  8. python 远程控制电脑开机_Python黑科技:在家远程遥控公司电脑,python+微信一键连接!...

    有时候需要远程家里的台式机使用,因为我平时都是用 MAC 多,但是远程唤醒只能针对局域网,比较麻烦,于是我想用微信实现远程唤醒机器. 准备工作 本程序主要是实现远程管理 Windows10操作系统的开 ...

  9. 记一次在家办公远程公司数据库的解决方案

    记一次在家办公远程公司数据库的解决方案 参考文章: (1)记一次在家办公远程公司数据库的解决方案 (2)https://www.cnblogs.com/jkguo/p/11188706.html 备忘 ...

最新文章

  1. ubuntu18.04上安装ffmpeg
  2. IP与DSCP优先级
  3. SAP CRM material上传调试
  4. 机器学习多元线性回归_过度简化的机器学习(1):多元回归
  5. 树状数组的建树 单点修改 单点查询 区间修改 区间查询
  6. 手机系统安装打印机服务器错误代码,OKI打印机报错?各型号代码故障解决方法...
  7. iOS警报– UIAlertController
  8. 牛客(3)从尾到头打印链表
  9. CLR探索系列:深入追踪托管exe加载执行过程
  10. mysql无法授权问题
  11. (转载)php flush()刷新不能输出缓冲的原因分析
  12. 邱锡鹏DL经典-神经网络与深度学习
  13. ShadowGun: Optimizing for Mobile Sample Level
  14. JAVA自学-day13-StringBuffer类、数组高级以及Arrays、Integer类
  15. DIY 1U硬件防火墙实录
  16. matlab求解积分总结
  17. 京东云服务器搭建mysql+jdk+tomact
  18. vue如何做Seo优化
  19. 5款主流智能音箱入门款测评:苹果小米华为天猫小度,谁的表现更胜一筹?
  20. win10插拔U盘、鼠标、键盘等外设的一瞬间,屏幕会闪黑一下

热门文章

  1. 西门子PLC学习笔记二-(工作记录)
  2. mysql5.6热升级_mysql 5.6 后热数据的加载
  3. 动态规划—最长公共子序列问题 HDU-1159 Common Subsequence
  4. 利用Python制作简单的小程序:IP查看器
  5. 博客园的博客积分与排名查看方法
  6. oracle测试环境表空间清理
  7. 最长递增子序列的两种解法
  8. 今天开始搞CentOS 7
  9. StringBuilder、StringBuffer、String区别
  10. 【青少年编程竞赛交流】12月份微信图文索引