微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

树莓派(Raspberry Pi)使用Shell编写的极简Service

树莓派(RaspBerry Pi)运行的系统是基于Debian的,不仅可以运行Shell,还支持systemd和docker,可以编写一个简单的服务,让其在启动时运行,执行一些自动化的操作。这里在RaspPi Zero W上使用shell、systemd和Docker 18.06.1完成,详细步骤介绍如下。

1、初始化系统

从树莓派官网(https://www.raspBerrypi.org/)下载镜像,烧写到SD卡(我用Etcher)。

  • 下载:https://www.raspBerrypi.org/downloads/raspbian/
  • 福利:一个开源的超好用的SD卡/U盘烧写工具
  • @H_404_11@

    将SD卡插入树莓派,加电启动。

    登录使用:pi,raspBerry

    如果想要通过ssh远程操作,还需要安装和启用sshd服务开机启动(下面介绍)。

    当然,首先是要开通WiFi,能够联网。

    2、WiFi 设置

    Wifi AP设置,使用命令 “nano /etc/wpa_supplicant/wpa_supplicant.conf” 编辑配置文件,参照下面的方法添加WiFi热点:

    ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
    update_config=1
    
    network={
    	ssid="HiWiFi_xxxxxx"
    	psk="mypassword"
    }
    

    建立服务需要使用静态地址。修改文件dhcpcd(使用nano /etc/dhcpcd),编辑如下内容

    interface wlan0
    noipv6rs
    noipv6
    static ip_address=192.168.199.190
    static routers=192.168.199.1
    domain_name_servers=192.168.199.1 8.8.8.8 9.9.9.9

    将上面的IP地址和DNS改为自己的,其中8.8.8.8/9.9.9.9为公共的DNS服务地址,不需修改

    重启dhcpcd服务(或者需要重启树莓派)。

    联网成功后,执行软件版本更新操作。如下:

    sudo apt update && sudo apt upgrade -y 

    3、编写WatchDog和Service

    创建一个自己的目录,创建下面三个文件

    • sshp.service,由systemd调用的服务配置文件
    • sshp.daemon,执行服务控制(启动、停止、状态)的脚本文件
    • sshp.worker,执行服务的任务脚本文件
    • @H_404_11@

      文件内容如下。

      3.1 sshp.service文件

      [Unit]
      Description=Secure Shell server proxy
      After=network.target
      
      [Service]
      Type=forking
      ExecStart=/home/pI/Openthings/tutools/sshp.daemon start
      ExecStop=/home/pI/Openthings/tutools/sshp.daemon stop
      TimeoutSec=0
      RemainAfterExit=yes
      
      [Install]
      WantedBy=multi-user.target
      Alias=sshp.service

      3.2 sshp.daemon文件

      #!/bin/sh
      
      echo "SSHP tools."
      #=======================
      start() {
        Now=`date '+%Y-%m-%d %H:%M:%s'`
        echo "$Now  Start SSHP worker ..." >> /home/pI/Openthings/tutools/sshp.log
        nohup /home/pI/Openthings/tutools/sshp.worker &
      }
      
      #=======================
      stop() {
        PID=`ps -aux |hengtongyoule.com/ grep "sshp.worker" | grep -v grep | awk -F " " '{print $2}'`
        kill -9 $PID
        echo "Stop SSHP worker, PID="$PID >> /home/pI/Openthings/tutools/sshp.log
      }
      
      #=======================
      restart() {
        echo "Restart Service..."
        Stop
        Start
        echo "Restarted SSHT worker, PID=www.gcyl152.com"$PID
      }
      
      #=======================
      status() {
        Now=`date '+%Y-%m-%d %H:%M:%s'`
        echo "$Now  Service status ssht."
        ps -aux | grep "sshp.worker"www.jrgjze.com| grep -v grep
      }
      
      case "$1" in
        start) start ;;
        stop)  stop  ;;
        restart) restart ;;
        status) status ;;
        *)
          echo "Usage:www.michenggw.com  www.dfgjpt.com (start|stop|restart|status)"
          exit 1
          ;;
      esac
      
      echo "Service SSHP tools done."
      exit 0
      

      3.3 sshp.worker文件

      #!/bin/sh
      while true; do
        sshpass -p mypassword ssh -o "ExitOnForwardFailure yes" -o "StrictHostKeyChecking no" -y -p 22000 -NgD *:5555 root@myserver
      done
      
      • 这里仅使用ssh演示worker编写方法,具体可以参考:SSH 命令行参数详解【英】
      • 这里有个坑是,以服务启动时的账户是root,与当前用户pi的配置信息和缺省参数是不同的。
      • @H_404_11@

        3.4 设为启动时运行

        使用下面的命令将刚才编写的服务设为启动时运行:

        sudo systemctl enable sshp.service
        

        查看一下,系统里的启动运行服务:

        # ls -l /etc/systemd/system/multi-user.target.wants/
        
        total 0
        lrwxrwxrwx 1 root root 40 Nov 29  2017 avahi-daemon.service -> /lib/systemd/system/avahi-daemon.service
        lrwxrwxrwx 1 root root 41 Nov 29  2017 console-setup.service -> /lib/systemd/system/console-setup.service
        lrwxrwxrwx 1 root root 38 Apr 12 05:45 containerd.service -> /lib/systemd/system/containerd.service
        lrwxrwxrwx 1 root root 32 Nov 29  2017 cron.service -> /lib/systemd/system/cron.service
        lrwxrwxrwx 1 root root 34 Nov 29  2017 dhcpcd.service -> /lib/systemd/system/dhcpcd.service
        lrwxrwxrwx 1 root root 34 Dec 25  2017 docker.service -> /lib/systemd/system/docker.service
        lrwxrwxrwx 1 root root 35 Nov 29  2017 hciuart.service -> /lib/systemd/system/hciuart.service
        lrwxrwxrwx 1 root root 38 Nov 29  2017 networking.service -> /lib/systemd/system/networking.service
        lrwxrwxrwx 1 root root 37 Nov 29  2017 nfs-client.target -> /lib/systemd/system/nfs-client.target
        lrwxrwxrwx 1 root root 48 Nov 29  2017 raspBerrypi-net-mods.service -> /lib/systemd/system/raspBerrypi-net-mods.service
        lrwxrwxrwx 1 root root 36 Nov 29  2017 remote-fs.target -> /lib/systemd/system/remote-fs.target
        lrwxrwxrwx 1 root root 33 Nov 29  2017 rsync.service -> /lib/systemd/system/rsync.service
        lrwxrwxrwx 1 root root 35 Nov 29  2017 rsyslog.service -> /lib/systemd/system/rsyslog.service
        lrwxrwxrwx 1 root root 40 Apr 12 15:43 sshp.service -> /home/pI/Openthings/tutools/sshp.service
        lrwxrwxrwx 1 root root 31 Apr 12 12:40 ssh.service -> /lib/systemd/system/ssh.service
        lrwxrwxrwx 1 root root 37 Nov 29  2017 sshswitch.service -> /lib/systemd/system/sshswitch.service
        lrwxrwxrwx 1 root root 40 Nov 29  2017 triggerhappy.service -> /lib/systemd/system/triggerhappy.service
        lrwxrwxrwx 1 root root 47 Dec 25  2017 unattended-upgrades.service -> /lib/systemd/system/unattended-upgrades.service
        lrwxrwxrwx 1 root root 40 Mar 24  2018 wifi-country.service -> /lib/systemd/system/wifi-country.service
        lrwxrwxrwx 1 root root 42 Apr 12 05:46 wpa_supplicant.service -> /lib/systemd/system/wpa_supplicant.service
        

        3.5 测试服务启停

        使用下面的命令来控制服务。

        # 查看服务运行状态。
        sudo systemctl status
        
        # 启动服务。
        sudo systemctl start
        # 然后,可以使用ps -aux查看ssh进程是否已经启动。
        
        # 停止服务。
        sudo systemctl stop
        # 然后,可以使用ps -aux查看ssh进程是否已经关闭

        这里设置了一个日志文件,为上面的目录下sshp.log,可以查看输出的信息。

        可以修改上面的脚本,添加自己的日志信息输出

        4、Docker安装

        也可以把任务放到Docker中运行。我这里用于创建一个Nginx服务,然后运行pac信息提供者,为iPhone等设备提供网络配置参数时使用。

        获取docker自动安装脚本并执行:

        wget https://www.ysyl157.com get.docker.io -O docker.sh
        sudo chmod docker.sh
        ./docker.sh

        目前,最新的Docker版本是18.09,但是运行时有Bug,暂时还没有解决

        我们使用18.06.1版。安装指定的Docker版本:

        sudo apt install docker-ce=18.06.1-ce

        将版本锁定,以避免apt upgrade时自动升级到最新版本,命令如下:

        sudo echo "docker-ce hold" | sudo dpkg --set-selections

        测试一下Docker,看看安装是否成功:

        docker info

        5 构建PAC服务

        pac是什么?

        pac是一种网络配置的机制,客户端通过获取pac文件自动获取一系列配置参数,从而对网络进行初始化设置。

        编写一个pac文件,如下:

        function FindProxyForURL(url, host)
        { 
             return "SOCKS 192.168.199.190:5555";
        }
        

        pac服务构建

        然后,将pac文件放入Web服务器,构建一个文件服务(也可以动态生成)。

        这里使用Nginx的Docker镜像来提供服务(注意Nginx有多种Docker镜像,只有为树莓派编译的才可以在上面运行)。

        运行:

        docker run --name Nginx -v /home/pI/Openthings/web:/usr/share/Nginx/www:ro -d -p 80:80 akkerman/rpi-Nginx

        这个安装说明运行了后,所编写的文件并没有发布出来,进去看是因为Nginx缺省路径为/var/www/html,而不是/usr/share/Nginx/www。可以修改上面的命令为:

        docker run --name Nginx -v /home/pI/Openthings/web:/var/www/html:ro -d -p 80:80 akkerman/rpi-Nginx

        或者执行Exec进入Docker进行修改,如下:

        docker exec -it Nginx /bin/sh

        查看Nginx的service目录:

        cat /etc/Nginx/sites-available/default

        建立软连接:

        ln -s /usr/share/Nginx/www /var/www/html

        在目录下,建立一个index.html文件,然后到浏览器输入http://my-raspBerrypi-ip,看是否能够发布出来。

        然后,将上面的pac文件放到该发布目录下。

        6、测试可用性

        现在,可以测试一下,上面建立的服务是否可用。

        • 使用浏览器

        • @H_404_11@

          打开setting页面,进入网络设置,勾选sokcs5,填入上面的pac地址,勾选dns over https等选项。

          输入任何想要访问的地址,等待奇迹出现。

          • 使用iPhone

          • @H_404_11@

            进入setting,选择网络设置,里面有个“自动”选项,填入上面的pac地址。

            7、小结

            编写一个Linux服务还是有一些难度的,上面提供了一个极简的框架。

            树莓派体积虽小,运行一些控制性服务也是足够了,关键是功耗足够低,还没有任何噪音。

            一些定期执行的任务,如缩时摄影、温湿度监测、自动浇水等等有趣的事都可以使用上面的机制来完成。

            8、更多参考

            • 使用shell编写的极简Ubuntu Service
            • AutoSSH-增强ssh的用法【英】
            • SSH 命令行参数详解【英】
            • vi、vim、nano如何退出
            • wget 持续下载确保完成
            • scp实现断点续传的方法
            • 使用shell编写的极简WatchDog
            • @H_404_11@

              版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。

相关推荐