V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Distributions
Ubuntu
Fedora
CentOS
中文资源站
网易开源镜像站
freaks
V2EX  ›  Linux

想请教各位 v2 shell 脚本比较精通的,被这个问题卡住了.

  •  
  •   freaks · 2022-04-16 08:42:12 +08:00 via iPhone · 4888 次点击
    这是一个创建于 937 天前的主题,其中的信息可能已经有所发展或是发生改变。
    自己写了个检测宽带公网出口 ip 变化的脚本,并通过企微的群聊机器人通知,想放到后台一直运行,但都是运行了:
    nohup sh scriptName.sh > /dev/null 2>&1 & 后 使用 ps - ef | grep scriptName.sh 后显示了一次,在此运行命令就看不到运行了。我用 bash -x script Name.sh 可以运行成功,也可以发起通知,但就是放不到后台执行,不知道哪里出问题了,还请各位大神不吝赐教,小弟在此谢过了. 搜了好多文章也没找到问题原因,要😭了.
    34 条回复    2022-04-19 10:06:31 +08:00
    Tink
        1
    Tink  
       2022-04-16 08:49:09 +08:00 via Android   ❤️ 1
    你这个脚本里面实现了一直循环?如果没有的话要用 cron
    DCCooper
        2
    DCCooper  
       2022-04-16 08:50:54 +08:00 via iPhone
    脚本退出了
    liangkang1436
        3
    liangkang1436  
       2022-04-16 09:10:40 +08:00 via Android
    @DCCooper 你要不做成服务算了,启动,停止都方便些
    plko345
        4
    plko345  
       2022-04-16 09:14:09 +08:00 via Android
    那你把结果重定向到文本里呀,可能脚本不健壮,某次失败退出了,你全都指向 null ,有问题也发现不了
    zhouzm
        5
    zhouzm  
       2022-04-16 09:18:28 +08:00
    # check-gateway.sh
    #! /bin/bash

    [[ ! -z "$1" ]] && host=$1 || host=192.168.1.1

    c=0
    last=0
    # while [[ $c -lt 100 ]]; do
    while true; do
    ping -q -c 1 -W 1 $host >/dev/null
    current=$?
    if [[ $current == 0 ]]; then
    if [[ $last != 0 || $c -eq 0 ]]; then
    last=$current
    echo $( date +%Y-%m-%d\|%H:%M:%S ) :$host online >> /run/check-gateway.log
    fi
    else
    if [[ $last == 0 ]]; then
    last=$current
    echo $( date +%Y-%m-%d\|%H:%M:%S ) :$host offline >> /run/check-gateway.log
    fi
    fi
    c=$(( $c + 1 ))
    sleep 1
    done
    exit 0



    nohup check-gateway.sh $IP >/dev/null 2>&1 &
    ch2
        6
    ch2  
       2022-04-16 09:19:21 +08:00 via iPhone
    有两个选择:
    1. 用 crontab 做成定时任务,每分钟检测一次,每次只跑完就退
    2.用 systemctl 做成服务,常驻后台
    lcy630409
        7
    lcy630409  
       2022-04-16 09:48:58 +08:00
    这个最简单的就是 crontab 了,定时执行即可
    freaks
        8
    freaks  
    OP
       2022-04-16 12:12:45 +08:00 via iPhone
    @Tink 就是写了个函数 if 判断下,和随便伪造的一个 IP 比对下,如果不同,就调用函数发到群聊里,相同就把信息输出到一个文本文件,然后不发告警.
    freaks
        9
    freaks  
    OP
       2022-04-16 12:13:26 +08:00 via iPhone
    @DCCooper 即没返回 127 也没返回 128
    freaks
        10
    freaks  
    OP
       2022-04-16 12:14:14 +08:00 via iPhone
    @liangkang1436 感觉像运行一次就结束了,达不到实时监控的目的
    freaks
        11
    freaks  
    OP
       2022-04-16 12:15:08 +08:00 via iPhone
    @plko345 我不指向空,也是默认追加到 nohup.out 没有报错的
    freaks
        12
    freaks  
    OP
       2022-04-16 12:17:20 +08:00 via iPhone
    @zhouzm 这个脚本是检测网关的吗?我是要检测出口公网 IP 隔一段时间改变,作提醒,还是感谢回答,我再研究研究
    freaks
        13
    freaks  
    OP
       2022-04-16 12:20:22 +08:00 via iPhone
    @ch2 有考虑过这样,但总感觉这个问题很简单,但自己又实在想知道原因,定时任务每分钟运行,可能造成日志过大,如果把周期拉长,可能会有探测不到变化的情况,不知道理解对不对.
    freaks
        14
    freaks  
    OP
       2022-04-16 12:21:09 +08:00 via iPhone
    @lcy630409 实在没招了,会考虑,不过现在确实卡住了😂
    Tink
        15
    Tink  
       2022-04-16 12:32:18 +08:00 via Android
    @freaks 按你的意思,你的脚本里面本身就是只执行一次啊,要么你就外面套一个死循环,要么就用 cron 定时一分钟运行一次
    freaks
        16
    freaks  
    OP
       2022-04-16 12:34:59 +08:00 via iPhone
    #!/bin/bash

    #存放变化 IP 的文件

    dirfile="/home/ip_change"

    # 获取 IP

    IP=`curl -s ip.sb`

    log="/var/log/tool.log"

    datetime=`date '+%Y-%m-%d %H:%M:%S'`

    if [ ! -f "$dirfile" ]; then
    touch "$dirfile"
    echo "1.1.1.1">$dirfile
    fi


    # 判断公网 IP 是否获取

    if [ ! -n "$IP" ]; then
    echo "$datetime 公网 IP 获取失败,检查'curl -s ip.sb'">> $log
    exit 1
    fi

    # 查看老 ip

    old_ip=`cat $dirfile`


    # 调用微信群聊机器人接口

    wx_web(){
    cat > sendweb.sh << EOF
    curl 'https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=' \
    -H 'Content-Type: application/json' -d \
    '{ \
    "msgtype": "text", \
    "text": { \
    "content": "公司外网发生了变化 新的 IP: ${IP} 老的 IP: ${old_ip} !!!" \
    } \
    }'
    EOF
    chmod +x sendweb.sh
    sh sendweb.sh && rm -rf sendweb.sh
    }

    if [ "$IP" = "$old_ip" ]; then
    echo "$datetime IP 正常 - true " >> $log
    else
    echo $IP > $dirfile
    wx_web
    fi
    freaks
        17
    freaks  
    OP
       2022-04-16 12:35:54 +08:00 via iPhone
    @Tink 下面放了脚本,希望大佬帮忙看看
    yaoyao1128
        18
    yaoyao1128  
       2022-04-16 12:38:57 +08:00 via iPhone
    没 loop……
    aaa5838769
        19
    aaa5838769  
       2022-04-16 12:48:26 +08:00
    可以 while 死循环脚本,丢到后台运行。或者用计划任务。
    freaks
        20
    freaks  
    OP
       2022-04-16 12:50:29 +08:00 via iPhone
    @aaa5838769 好吧,还是代码的问题,这个是不是在 if 那里加就行了?
    felixcode
        21
    felixcode  
       2022-04-16 13:59:11 +08:00
    用 cronjob 或 systemd 做吧,还能看看执行日志,nohup 太山寨了
    oneisall8955
        22
    oneisall8955  
       2022-04-16 14:04:04 +08:00 via Android
    在 cron 定时知道就行了
    Cbdy
        23
    Cbdy  
       2022-04-16 14:29:25 +08:00 via Android
    可以用 pm2
    pengtdyd
        24
    pengtdyd  
       2022-04-16 14:51:31 +08:00
    我就是脚本小王子,哈哈哈哈。盲猜 99%是因为脚本里面报错,所以进程退出了。
    freaks
        25
    freaks  
    OP
       2022-04-16 15:02:06 +08:00 via iPhone
    @oneisall8955 已经使用定时任务替代,用 systemd 可以不加 while 一直运行吗
    zhouzm
        26
    zhouzm  
       2022-04-16 15:26:49 +08:00
    你的脚本是在 linux 下运行还是在 openwrt 下运行?
    zhouzm
        27
    zhouzm  
       2022-04-16 15:39:22 +08:00   ❤️ 1
    上面有人说 nohup 太山寨这种说法是不妥的,cron 只支持最小 1 分钟的间隔频率,如果对监控结果实时性敏感度高的话,用脚本循环判断是比较简便的方案。

    @freaks 我上面给的脚本是我一直在用的,用途是判断网关是否在线,是完整的循环处理代码,你只需要把 while 循环内代码替换成你的检测脚本就可以了。
    手动运行测试的时候可以把 while true; do 注释掉,使用上面一行,100 是你想测试循环的次数,测试不报错后再改成一直循环,然后 nohup check-gateway.sh $IP >/dev/null 2>&1 & 运行就可以了。

    bash 的 sleep 是不消耗 cpu 的,可以放心大胆的使用。
    freaks
        28
    freaks  
    OP
       2022-04-16 16:20:31 +08:00 via iPhone
    @zhouzm 非常感谢🙏提供思路,我这里就是 Linux 系统下,这东西存在就有意义,不然不早被拿掉了,说山寨未免太那个了。我抽空试试你的方法,现在先 crontab 一段时间.
    Cu635
        29
    Cu635  
       2022-04-16 16:25:18 +08:00
    @zhouzm
    @freaks
    说 nohup 山寨是因为有了更好用的 screen 吧……
    huntagain2008
        30
    huntagain2008  
       2022-04-16 16:31:41 +08:00
    新手昨天刚看到 1983 年 unix 编程环境 5.3while 和 until
    $cat watch who
    ...
    while : # coop forever
    do
    who>$new
    diff $new $old
    sleep 60
    done
    ...
    $
    :是 shell 内部命令,它仅仅计算参数值,然后返回“真”。while 循环体,只要命令返回状态为真便继续执行。还可以自定义时间间隔
    $cat check mail
    ...
    t=$(1-60)
    ...
    $
    时间间隔依然设为 60 秒,但在命令行提供了一个参数,如果键入下面命令
    $ checkmail 30
    就使用新的时间参数。如果提供了时间参数,shell 变量 t 被设为对应的时间间隔,如果未提供,缺省时间间隔为 60 秒
    felixcode
        31
    felixcode  
       2022-04-16 16:50:32 +08:00
    说 nohup 山寨是因为缺乏基本的监测控制。
    这个程序是作为监测服务运行的,如果 nohup 进程挂了,不会自动重启,也不会有任何通知,而管理员是完全不知道的。
    用 systemd 就能避免这样的情况,cron 的话可以不在意前面的运行是否成功。
    baobao1270
        32
    baobao1270  
       2022-04-17 06:33:22 +08:00   ❤️ 1
    上面说用 systemd 做成 service 的都是什么人啊
    systemd 的正确用法是做成 timer
    felixcode
        33
    felixcode  
       2022-04-17 12:13:36 +08:00 via Android
    @baobao1270 既能用 timer 也能用来控制循环脚本啊,用法又不唯一
    hcql
        34
    hcql  
       2022-04-19 10:06:31 +08:00
    可以使用这种

    #!/bin/sh
    while true; do
    "checkyouripcommad"
    done
    sleep 60
    done
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1849 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 16:29 · PVG 00:29 · LAX 08:29 · JFK 11:29
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.