美文网首页
ssh 状态下如何后台运行程序?谁来保证远程会话的持续性?这篇文

ssh 状态下如何后台运行程序?谁来保证远程会话的持续性?这篇文

作者: 张清柏 | 来源:发表于2021-09-23 21:57 被阅读0次

    对于刚接触linux的同学,可能有这样的体验:

    • 使用ssh登录到服务器后,执行了一个耗时较长的脚本,有时因为网络不稳定或者手滑导致ssh远程连接断开,导致程序执行失败。

    • 需要长时间稳定跑的脚本。我们希望能够在linux后台跑,关闭远程连接也没事,且可以随时查看输出信息或者操作

    • tips: 以下操作基于centos7

    举栗子看一下

    # vi /etc/ssh/sshd_config
    ClientAliveInterval 2m          # 2 minutes
    ClientAliveCountMax 0            # 0 次
    
    #重启ssh服务
    # service sshd restart  
    
    
    • 编写shell 脚本,循环往一个文件里面写入数字,到120s 会断开连接
    #!/bin/bash
    
    for((i=1;i<=100000;i++));
    do
    echo "$i " >>num.log;
    sleep 1
    done
    
    • 超时断开

      - 超时断开
    • 进程已经被关闭


      进程已经关闭

    这里简单介绍一下ps -ef 每列的含义
    字段含义如下:
    UID PID PPID C STIME TTY TIME CMD
    root 18887 18828 0 08:09 pts/0 00:00:00 grep ApacheJetspeed

    ps:将某个进程显示出来
    -A  显示所有程序。
    -e  此参数的效果和指定”A”参数相同。
    -f  显示UID,PPIP,C与STIME栏位。
    grep命令是查找
    中间的|是管道命令 是指ps命令与grep同时执行
    UID PID PPID C STIME TTY TIME CMD
    root 18887 18828 0 08:09 pts/0 00:00:00 grep ApacheJetspeed

    各相关信息的意义:

    UID 程序被该 UID 所拥有

    PID 就是这个程序的 ID

    PPID 则是其上级父程序的ID

    C CPU 使用的资源百分比

    STIME 系统启动时间

    TTY 登入者的终端机位置

    TIME 使用掉的 CPU 时间。

    CMD 所下达的指令为何

    • 共写入了120次,即120s


      共写入了120次
    • 原因:
      在linux 里面,所有的进程都有父进程,当ssh连接到服务器上时,打开的shell就是你所有执行命令的父进程,因为你所有的命令都是基于shell里面去执行的。那么当shh断开连接的时候,父进程就退出了,由于我们没有做特殊处理,系统收到父进程的sigterm信号,父进程下面的子进程会被全部kill掉

    解决方案:

    • nohup
    [root@localhost ~]# nohup ./for.sh  &
    [1] 6326
    [root@localhost ~]# nohup: ignoring input and appending output to ‘nohup.out’
    
    • screen
    # 使用yum安装screen
    yum install screen
    # 创建一个名为test的会话窗口
    screen -S test
    # 暂离窗口
    Ctrl+a d(即按住Ctrl,依次再按a,d)
    # 查看存在的会话窗口
    screen -ls
    # 进入窗口
    screen -r test
    screen -r 进程ID
    # 关闭窗口
    exit
    # 窗口切换
    Ctrl+a c :在当前screen会话中创建窗口
    Ctrl+a w :窗口列表
    Ctrl+a n :下一个窗口
    Ctrl+a p :上一个窗口
    Ctrl+a 0-9 :在第0个窗口和第9个窗口之间切换
    
    • tmux 相关参考
      Tmux是一个优秀的终端复用软件,类似GNU Screen,但来自于OpenBSD,采用BSD授权。使用它最直观的好处就是,通过一个终端登录远程主机并运行tmux后,在其中可以开启多个控制台而无需再“浪费”多余的终端来连接这台远程主机。是BSD实现的Screen替代品,相对于Screen,它更加先进:支持屏幕切分,而且具备丰富的命令行参数,使其可以灵活、动态的进行各种布局和操作。
    ctrl+b ?            显示快捷键帮助
    ctrl+b 空格键       采用下一个内置布局,这个很有意思,在多屏时,用这个就会将多有屏幕竖着展示
    ctrl+b !            把当前窗口变为新窗口
    ctrl+b  "           模向分隔窗口
    ctrl+b %            纵向分隔窗口
    ctrl+b q            显示分隔窗口的编号
    ctrl+b o            跳到下一个分隔窗口。多屏之间的切换
    ctrl+b 上下键      上一个及下一个分隔窗口
    ctrl+b C-方向键    调整分隔窗口大小
    ctrl+b &           确认后退出当前tmux
    ctrl+b [           复制模式,即将当前屏幕移到上一个的位置上,其他所有窗口都向前移动一个。
    ctrl+b c           创建新窗口
    ctrl+b n           选择下一个窗口
    ctrl+b l           最后使用的窗口
    ctrl+b p           选择前一个窗口
    ctrl+b w           以菜单方式显示及选择窗口
    ctrl+b s           以菜单方式显示和选择会话。这个常用到,可以选择进入哪个tmux
    ctrl+b t           显示时钟。然后按enter键后就会恢复到shell终端状态
    ctrl+b d           脱离当前会话;这样可以暂时返回Shell界面,输入tmux attach能够重新进入之前的会话
    
    • linux 设置定时任务开启脚本
      • cron介绍
        我们经常使用的是crontab命令是cron table的简写,它是cron的配置文件,也可以叫它作业列表,我们可以在以下文件夹内找到相关配置文件。
        1./var/spool/cron/ 目录下存放的是每个用户包括root的crontab任务,每个任务以创建者的名字命名
        2./etc/crontab 这个文件负责调度各种管理和维护任务。
        3./etc/cron.d/ 这个目录用来存放任何要执行的crontab文件或脚本。
        4.我们还可以把脚本放在/etc/cron.hourly、/etc/cron.daily、/etc/cron.weekly、/etc/cron.monthly目录中,让它每小时/天/星期、月执行一次。

    我们上面介绍的这些,只能保证脚本的常驻运行,但是并不能保证脚本异常终止后的自动重启。接下来我们聊一聊supervisor

    • supervisor
      Supervisor 是用Python开发的一套通用的进程管理程序,能将一个普通的命令行进程变为后台daemon,并监控进程状态,异常退出时能自动重启。

    安装参考
    配置和使用参考

    cd /usr/local/src
    cd /usr/local/src
    
    wget https://pypi.python.org/packages/7b/17/88adf8cb25f80e2bc0d18e094fcd7ab300632ea00b601cbbbb84c2419eae/supervisor-3.3.2.tar.gz
    
    tar -zxvf supervisor-3.3.2.tar.gz
    
    cd supervisor-3.3.2
    
    python setup.py install
    

    Tips:错误1:ImportError: No module named setuptools

    ## 下载pip
    wget https://files.pythonhosted.org/packages/c2/f7/c7b501b783e5a74cf1768bc174ee4fb0a8a6ee5af6afa92274ff964703e0/setuptools-40.8.0.zip
    unzip setuptools-40.8.0.zip 
    cd setuptools-40.8.0
    python setup.py install
    

    Tips:错误2:error: Could not find suitable distribution for Requirement.parse(‘meld3>=0.6.5‘),安装meld扩展

    wget https://pypi.python.org/packages/45/a0/317c6422b26c12fe0161e936fc35f36552069ba8e6f7ecbd99bbffe32a5f/meld3-1.0.2.tar.gz#md5=3ccc78cd79cffd63a751ad7684c02c91
    tar zxvf meld3-1.0.2.tar.gz
    cd meld3-1.0.2
    python setup.py install
    

    安装完毕

    [root@localhost ~]# supervisord -v --查看版本号
    3.3.2
    [root@localhost ~]# echo_supervisord_conf > /etc/supervisord.conf --生成配置文件
    [root@localhost ~]# supervisord -c /etc/supervisord.conf --启动
    [root@localhost ~]# ps aux | grep supervisord  --查看进程
    root       9214  0.0  0.9 215256  9804 ?        Ss   06:41   0:00 /usr/bin/python /usr/bin/supervisord -c /etc/supervisord.conf
    root       9216  0.0  0.0 112808   964 pts/0    R+   06:41   0:00 grep --color=auto supervisord
    [root@localhost ~]# 
    # 查看最终配置文件
    [root@localhost etc]# cat supervisord.conf  |grep -v '^;' |grep -v '^$'
    
    [unix_http_server]
    file=/tmp/supervisor.sock   ; the path to the socket file
    [inet_http_server]         ; inet (TCP) server disabled by default
    # 注意ip的配置,后面说的很明白 如果需要局域网访问 需要写成 *:port
    port=*:9001        ; ip_address:port specifier, *:port for all iface
    username=admin              ; default is no username (open server)
    [supervisord]
    logfile=/tmp/supervisord.log ; main log file; default $CWD/supervisord.log
    logfile_maxbytes=50MB        ; max main logfile bytes b4 rotation; default 50MB
    logfile_backups=10           ; # of main logfile backups; 0 means none, default 10
    loglevel=info                ; log level; default info; others: debug,warn,trace
    pidfile=/tmp/supervisord.pid ; supervisord pidfile; default supervisord.pid
    nodaemon=false               ; start in foreground if true; default false
    minfds=1024                  ; min. avail startup file descriptors; default 1024
    minprocs=200                 ; min. avail process descriptors;default 200
    [rpcinterface:supervisor]
    supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface
    [supervisorctl]
    serverurl=unix:///tmp/supervisor.sock ; use a unix:// URL  for a unix socket
    [include]
    files = /etc/supervisord.conf.d/*.conf
    [root@localhost etc]#   
    
    

    通过浏览器访问一下(此处注意,如果是centos7 需要关闭防火墙systemctl stop firewalld 或者加入ip白名单均可)

    在这里插入图片描述
    • supervisorctl的用法
    supervisord : 启动supervisor
    
    supervisorctl reload :修改完配置文件后重新启动supervisor
    
    supervisorctl status :查看supervisor监管的进程状态
    
    supervisorctl start all | 进程名 :启动全部或某进程
    
    supervisorctl stop all | 进程名 :停止全部或某进程
    
    supervisorctl stop all:停止进程,注:start、restart、stop都不会载入最新的配置文件。
    
    supervisorctl update:根据最新的配置文件,启动新配置或有改动的进程,配置没有改动的进程不会受影响而重启
    # 读取有更新(增加)的配置文件,不会启动新添加的程序 
    $supervisorctl reread
     # 重启配置文件修改过的程序 
    $supervisorctl update
     # 查看程序状态 
    $supervisorctl status
     # 启动程序 App_name 
    $supervisorctl start App_name
     # 关闭程序 App_name 
    $supervisorctl stop App_name
     # 重启程序 App_name 
    supervisorctl -c /etc/supervisord.conf restart App_name:    
    supervisorctl -c /etc/supervisord.conf start App_name:App_name_01
    #supervisord **重载配置要用update ,不要用reload!
    
    $supervisorctl restart App_name
    以上命令也可以在supervisorctl Shell中执行:
    $supervisorctl
    supervisor>reread
    supervisor> update
    supervisor> status
    supervisor> start App_name
    supervisor> stop App_name
    supervisor> restart App_name
    
    
    
    • 创建一个任务
    [root@localhost supervisord.conf.d]# vi for.conf                                                                                                                                                                                              
    
    ; 设置进程的名称,使用 supervisorctl 来管理进程时需要使用该进程名
    [program:fornumber]
    command=/bin/sh /root/for.sh   ;具体命令
    ;numprocs=1                 ; 默认为1
    ;process_name=%(program_name)s   ; 默认为 %(program_name)s,即 [program:x] 中的 x
    ;directory=/home/python/tornado_server ; 执行 command 之前,先切换到工作目录
    user=root                 ; 使用 oxygen 用户来启动该进程
    ; 程序崩溃时自动重启,重启次数是有限制的,默认为3次
    autorestart=true
    redirect_stderr=true        ; 重定向输出的日志
    stdout_logfile = /var/log/supervisord/tornado_server.log
    loglevel=info
    

    重载配置文件supervisorctl reload
    启动服务supervisord -c /etc/supervisord.conf

    在这里插入图片描述

    在conf目录下,生成了num.log 文件,我刚开始也疑惑了一下,为什么日志打到了这个目录,一瞬间明白了,for.sh 里面有echo "$i " >>num.log; 就是输出当前目录,但是命令执行的时候就是以配置文件为脚本运行的目录了。所以我们写的时候最好写绝对路径。

    [root@localhost supervisord.conf.d]# ls
    for.conf  num.log
    
    在这里插入图片描述
    • 设置开机自启
    
    # vi supervisord.service 
    #supervisord.service
    
    [Unit] 
    Description=Supervisor daemon
    
    [Service] 
    Type=forking 
    ExecStart=/usr/bin/supervisord -c /etc/supervisord.conf 
    ExecStop=/usr/bin/supervisorctl shutdown 
    ExecReload=/usr/bin/supervisorctl reload 
    KillMode=process 
    Restart=on-failure 
    RestartSec=42s
    
    [Install] 
    WantedBy=multi-user.target
    
    

    将文件拷贝到/usr/lib/systemd/system/(注意文件的权限要可执行) cp supervisord.service /usr/lib/systemd/system/

    [root@localhost init.d]# systemctl enable supervisord
    Failed to execute operation: Access denied
    # 如果出现denied 输入下面命令
    [root@localhost init.d]# setenforce 0
    [root@localhost init.d]# systemctl enable supervisord
    Created symlink from /etc/systemd/system/multi-user.target.wants/supervisord.service to /usr/lib/systemd/system/supervisord.service.
    [root@localhost init.d]# systemctl is-enabled supervisord
    enabled
    

    其他参考

    https://blog.51cto.com/u_13677412/3673751

    https://www.zhihu.com/question/20709809

    相关文章

      网友评论

          本文标题:ssh 状态下如何后台运行程序?谁来保证远程会话的持续性?这篇文

          本文链接:https://www.haomeiwen.com/subject/jaxagltx.html