分类 默认分类 下的文章

Linux Shell获取CCTV5节目单

#!/bin/bash
#查询CCTV5节目表

<<'COMMENT'
API:
https://api.cntv.cn/epg/epginfo?serviceId=tvcctv&c=cctv5&d=20210617&cb=abccctv5&t=jsonp
https://api.cntv.cn/epg/epglist?serviceId=channel&t=jsonp&c=cctv5&cb=tv_box3

COMMENT

jsonp="abccctv5"
epgURL="https://api.cntv.cn/epg/epginfo?serviceId=tvcctv&c=cctv5&d=%date%&cb=abccctv5&t=jsonp"
if [ $# -eq 1 ] && [[ "${1,,}" == "n" ]]
then
    today=$(date +"%Y%m%d" -d '+1 day')
else
    today=$(date +"%Y%m%d")
fi

jsonData=$(curl -sSfL ${epgURL//%date%/$today}|sed -r "s/^${jsonp}\(//;s/\)\;?\$//")

echo "$jsonData"|jq -r '.cctv5.program[]|.showTime+"\t"+.t'

sp20210630_022853_679.png
附:获取CCTV5+节目表代码同理:

#!/bin/bash
#查询CCTV5+节目表

<<'COMMENT'
API:
https://api.cntv.cn/epg/epginfo?serviceId=tvcctv&c=cctv5plus&d=20210617&cb=abccctv5plus&t=jsonp
https://api.cntv.cn/epg/epglist?serviceId=channel&t=jsonp&c=cctv5plus&cb=tv_box3

COMMENT

jsonp="abccctv5plus"
epgURL="https://api.cntv.cn/epg/epginfo?serviceId=tvcctv&c=cctv5plus&d=%date%&cb=abccctv5plus&t=jsonp"
if [ $# -eq 1 ] && [[ "${1,,}" == "n" ]]
then
    today=$(date +"%Y%m%d" -d '+1 day')
else
    today=$(date +"%Y%m%d")
fi

jsonData=$(curl -sSfL ${epgURL//%date%/$today}|sed -r "s/^${jsonp}\(//;s/\)\;?\$//")

echo "$jsonData"|jq -r '.cctv5plus.program[]|.showTime+"\t"+.t'

扫描二维码,在手机上阅读!

Linux Bash/Shell获取爱快路由器WAN拨号时间和在线时长

家用宽带每隔一段时间会自动重播更换IP,对于经常需要确认外网IP变动或宽带重拨时间来进行一些自动化任务的朋友来说,确认宽带拨号时间很有用,以下Bash脚本实现不用登陆爱快路由器后台即可查看宽带在线时长和下次重拨时间:

#!/bin/bash
#查询爱快路由器WAN接口拨号联网时间
#1.替换IP地址10.10.10.3为你爱快路由器的实际IP
#2.注意使用浏览器F12抓包获取你自己的爱快用户和密码加密数据,替换xxxxx内容,此数据经过观察是固定不变的
##ikuai_wan_time.sh
cookieFile="/tmp/cookie.tmp.$$"

trap "rm -f $cookieFile" 0

StampToTime(){
    local connectTime
    if [ "$(type -t stamptotime)" = "file" ];
    then
        connectTime=$(stamptotime "$1")
    else
        connectTime=$(date +'%Y-%m-%d %H:%M:%S' -d "1970-01-01 UTC ${1} seconds")
    fi  
    echo "$connectTime"
}

curl -sSf 'http://10.10.10.3/Action/login' \
  -H 'Connection: keep-alive' \
  -H 'Pragma: no-cache' \
  -H 'Cache-Control: no-cache' \
  -H 'Accept: application/json, text/plain, */*' \
  -H 'DNT: 1' \
  -H 'User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36' \
  -H 'Content-Type: application/json;charset=UTF-8' \
  -H 'Origin: http://10.10.10.3' \
  -H 'Referer: http://10.10.10.3/login' \
  -H 'Accept-Language: zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7,de;q=0.6,zh-TW;q=0.5' \
  --data-binary '{"username":"admin","passwd":"xxxxxxxxxxxxxxxxxxxxxx","pass":"xxxxxxxxxxxxxxx","remember_password":""}' \
  --cookie-jar $cookieFile >/dev/null

wanInfo=$(curl -sSfL 'http://10.10.10.3/Action/call' \
  -H 'Connection: keep-alive' \
  -H 'Pragma: no-cache' \
  -H 'Cache-Control: no-cache' \
  -H 'Accept: application/json, text/plain, */*' \
  -H 'DNT: 1' \
  -H 'User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36' \
  -H 'Content-Type: application/json;charset=UTF-8' \
  -H 'Origin: http://10.10.10.3' \
  -H 'Referer: http://10.10.10.3/' \
  -H 'Accept-Language: zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7,de;q=0.6,zh-TW;q=0.5' \
  --data-binary '{"func_name":"syslog-wanpppoe","action":"show","param":{"TYPE":"total,data,interface","ORDER_BY":"id","ORDER":"desc","limit":"0,50"}}' \
  -b $cookieFile)

#echo "$wanInfo"|jq -r '.'

wanUptime=$(echo "$wanInfo"|jq -r '.Data.data[0].timestamp')
wanUptimeFull=$(StampToTime "${wanUptime}")

echo "爱快拨号状态查询:"

nowTimeStamp=$(date +%s)
startupTimeStamp=$wanUptime
wanOnlineTime=$(($nowTimeStamp-$startupTimeStamp))
nextTimeStamp=$(($startupTimeStamp+172800))
wanUpHourFull=$(echo "$wanOnlineTime"|awk '{printf "%.3f",$0/3600}')
wanUpHour=$(expr $wanOnlineTime / 3600 )
wanUpMin=$(expr \( $wanOnlineTime % 3600 \) / 60 )
connectTime=$(StampToTime "${startupTimeStamp}")
nextconnectTime=$(StampToTime "${nextTimeStamp}")


echo "联网时间戳:$startupTimeStamp"
echo "下次重拨时间戳:$nextTimeStamp"
echo "WAN在线时长(小时):$wanUpHourFull 小时"
echo "WAN在线时长(详细):$wanUpHour 小时 $wanUpMin 分"
echo "ADSL拨号联网时间:$connectTime"
echo "下次重连时间:$nextconnectTime"

sp20210630_022346_504.png


扫描二维码,在手机上阅读!

autossh自动化脚本,快速搭建多服务器SSH动态代理隧道,/v/bin/sshproxy

#!/bin/bash
SCRIPTPATH=$(realpath $0)
#执行autossh,自动创建SSH动态端口代理隧道

display_usage() {
    echo -e "$SCRIPTPATH\n"
    echo -e "\t执行autossh,自动创建SSH动态端口代理隧道."
    echo -e "\t默认绑定端口:0.0.0.0:8989."
    echo -e "\t参数1目的主机的为必选参数,其余为可选参数."
    echo -e "\nUsage:\n\tsshproxy [*hostname] [local proxy port] [kill exists process] [use http proxy or not(mustbe: nohttp)]"
    echo -e "Example1:\n\tsshproxy racknerd true"
    echo -e "Example2:\n\tsshproxy racknerd nohttp"
    echo -e "Example3:\n\tsshproxy racknerd 7171 true"
    echo -e "Example4:\n\tsshproxy racknerd 7171 nohttp"
    echo -e "Example5:\n\tsshproxy racknerd 7171 true nohttp"
    echo -e "\n附加用法:\n"
    echo -e "\t1.sshproxy kill  检测并杀死所有的代理进程"
    echo -e "\t2.sshproxy list  列出当前活动的所有代理"
    echo -e "\t3.sshproxy test  检测已有代理端口的可用性\n"
}
# if less than two arguments supplied, display usage
if [  $# -lt 1 ]
then
    display_usage
    exit 1
fi

# check whether user had supplied -h or --help . If yes display usage
if [[ ( $* == "--help") ||  $* == "-h" ]]
then
    display_usage
    exit 0
fi

do_KillProcess() {
    #首先尝试查询和保存代理各个端口
    local processPID=$(ps aux|grep 'ssh-for-proxy'|awk '{print $4}'|tr '\n' ' ')
    if [ ! -z "$processPID" ];then
        declare -a proxyPort ## 定义数组,存储找到的多个代理进程本地端口
        for pid in $processPID;
        do
            local port=$(netstat -ano|grep $pid|grep 'LISTENING'|grep 0.0.0.0|awk '{print $2;exit}'|awk -F ':' '{print $NF}')
            #echo "$port"
            proxyPort=(${proxyPort[@]} $port)
        done
    fi
    echo "kill Process..."
    killall autossh &> /dev/null
    killall ssh-for-proxy &> /dev/null
    killall goproxy-for-ssh &> /dev/null
    ## 关闭涉及各端口的TCP连接,以保万全
    echo "kill Connections..."
    for port in ${proxyPort[@]};
        do
            #echo "Close Port connection $port"
            gsudo `cygpath -w /v/bin/cports` /close '*' $port '*' '*'
        done
    return
}

do_ListProxy() {
    local psList=$(ps aux|grep 'ssh-for-proxy')
    local pids=$(echo "$psList"|awk '{print $1}')
    local winpids=$(echo "$psList"|awk '{print $4}')
    declare -a RemoteAddrs
    declare -a ListenAddrs
    declare -a ProxyAddrs
    declare -a HostAlias #查找 ~/.ssh/config以确定主机别名
    for pid in $(echo "$winpids");
    do
        local remoteAddr=$(netstat -ano -P TCP|grep $pid|grep 'ESTABLISHED'|awk '{print $3;exit}') #仅打印一行即退出
        [ -z "$remoteAddr" ] && remoteAddr="Unknown:Unknown\t"
        RemoteAddrs=(${RemoteAddrs[@]} $remoteAddr)
        local remoteIP=$(echo $remoteAddr|cut -d ':' -f 1)
        local hostName=$(python3 /v/bin/sshfindip.py $remoteIP|sed -n '1p')
        if [ ! -z "$hostName" ];then
            local hostName=$(echo "$hostName"|tr -s ' '|tr ' ' ','|sed -r 's/^Host\,//i')
        else
            local hostName="*Unknown*"
        fi
        HostAlias=(${HostAlias[@]} "$hostName")
        local listenAddr=$(netstat -ano -P TCP|grep $pid|grep 'LISTENING'|grep '0.0.0.0'|awk '{print $2;exit}') #仅打印一行即退出
        [ -z "$listenAddr" ] && listenAddr="Unknown:Unknown\t"
        ListenAddrs=(${ListenAddrs[@]} $listenAddr)
        local proxyAddr="socks5://127.0.0.1:"$(echo $listenAddr|awk -F ':' '{print $NF}')
        ProxyAddrs=(${ProxyAddrs[@]} $proxyAddr)
    done
    declare -a unixPids
    declare -a winPids
    local unixPids=($(echo "$pids"|tr '\n' ' '))
    local winPids=($(echo "$winpids"|tr '\n' ' '))
    local proxyIndex=0
    local showType="listen"
    [ ! -z "$2" ] && showType="proxy"
    if [[ $showType == "listen" ]];then
        echo -e "PID\tWINPID\tRemote Address\t\tLocal Address\tHostName\n"
    else
        echo -e "PID\tWINPID\tRemote Address\t\tProxy Address\t\tHostName\n"
    fi
    for proxyNum in ${RemoteAddrs[@]};
    do
        #本地信息显示方式:代理地址 OR 监听地址
        #local showLocal=${ListenAddrs[$proxyIndex]} ##本地监听地址
        #local showLocal=${ProxyAddrs[$proxyIndex]} ##Socks代理地址
        if [[ $showType == "listen" ]];then
            local showLocal=${ListenAddrs[$proxyIndex]}
        else
            local showLocal=${ProxyAddrs[$proxyIndex]}
        fi
        echo -e "${unixPids[$proxyIndex]}\t${winPids[$proxyIndex]}\t$proxyNum\t$showLocal\t${HostAlias[$proxyIndex]}"
        let proxyIndex+=1
    done
}

do_TestProxy() {
    # 当前已适配开启多个Proxy进程的情况
    local processPID=$(ps aux|grep 'ssh-for-proxy'|awk '{print $4}'|tr '\n' ' ')
    if [ ! -z "$processPID" ];then
        #local proxyPort=$(netstat -ano|grep $processPID|grep 'LISTENING'|grep 0.0.0.0|awk '{print $2;exit}'|awk -F ':' '{print $NF}')
        #local proxyPort=$(netstat -ano|grep $processPID|grep 'LISTENING'|grep 0.0.0.0|awk '{print $2}')
        declare -a proxyPort ## 定义数组,存储找到的多个代理进程本地端口
        for pid in $processPID;
        do
            local port=$(netstat -ano|grep $pid|grep 'LISTENING'|grep 0.0.0.0|awk '{print $2;exit}'|awk -F ':' '{print $NF}')
            #echo "$port"
            proxyPort=(${proxyPort[@]} $port)
        done
    fi
    #echo "${proxyPort[@]}" ##数组:存储找到的所有代理的端口
    
    if [ ! -z "$processPID" -a ! -z "$proxyPort" ];then
        for dstport in ${proxyPort[@]};
        do
            echo "proxyPort:$dstport"
            echo "Proxy Address:127.0.0.1:$dstport"
            echo "Full Proxy Address:socks5://127.0.0.1:$dstport"
            nc -w 2 -v 127.0.0.1 $dstport
            curl --connect-timeout 3 -sS -x socks5://127.0.0.1:$dstport 'http://v.ynit.top/ipfull/'
            echo -e "\n"
        done
        return 0
    else
        echo "proxyPort not Found!"
    fi
}

if [[ $* == "kill" ]]
then
    do_KillProcess $@
    exit 0
fi

if [[ $* =~ ^list$ || $* =~ "list " ]]
then
    do_ListProxy $@
    exit 0
fi

if [[ $* == "test" ]]
then
    do_TestProxy $@
    exit 0
fi

proxyPort=8989
targetHost=$1
noHTTP=false

if [ $# -ge 2 ] && [ ! -z "$2" ];then
    #判断第二个参数是否为纯数字,如果是数字,则认定为自定义代理的本地端口
    expr $2 "+" 10 &> /dev/null  
    if [ $? -eq 0 ];then
        proxyPort=$2
        shift
    fi
fi

#proxyProcess=$(netstat -ano -P TCP|grep ':'$proxyPort)
proxyProcess=$(netstat -ano -P TCP|grep ':'$proxyPort|grep 'LISTENING')

if [ $(echo -n "$proxyProcess"|wc -c) -gt 0 ];then
    #echo "有进程..."
    echo "$proxyProcess"
    if [ ! -z "$2" ] && [[ "$2" == "true" ]];then
        ## 不询问用户,直接杀死已有的进程
        do_KillProcess      
    else
        echo "已有代理进程存在,是否杀死进程?"
        read -p "是否终止已有进程?选择否本脚本将退出后续操作。y/n(默认为n)" killProcess
        if [ -z "$killProcess" ];then
            killProcess="no"
        fi
        if [[ "$killProcess" == "y" || "$killProcess" == "yes" ]];then
            do_KillProcess
        else
            exit 0
        fi
    fi
    :;
else
    #echo "无进程..."
    :;
fi

# 如果指定了不询问即终止进程的参数,此处$*参数前移一位
[ $# -ge 3 ] && shift 1

# 是否需要启动HTTP代理,默认均启动socks转http,端口号为socks端口前面加1,$2设为“nohttp”则不启动。
# 下面用tr统一转字符串为小写比较
if [ ! -z "$2" ] && [[ $(tr "[:upper:]" "[:lower:]" <<<"$2") == "nohttp" ]];
then
    noHTTP=true
fi

#从5656端口开始到5700,找到一个未占用的端口作为autossh管理端口
managePort=5656
manageOK=false
while [ !$manageOK -a $managePort -lt 5701 ];
do 
    #echo "循环中"
    #nc -w 2 -v 127.0.0.1 $managePort &> /dev/null
    netstat -ano -P TCP|grep 'LISTENING'|grep '127.0.0.1:'$managePort &> /dev/null
    if [ $? -ne 0 ];then
        manageOK=true
        break
    fi
    #echo "查询下一个端口"
    let managePort+=1
done
if [[ $manageOK == false ]];then
    echo "未找到可用的管理端口,程序罢工退出"
    exit 1
fi
echo "autossh使用管理端口:$managePort"

goProxyPort="1"$proxyPort

AUTOSSH_PATH=/v/bin/ssh-for-proxy autossh -M $managePort -C -N -f -D 0.0.0.0:$proxyPort $targetHost
echo "Proxy Address:127.0.0.1:$proxyPort"
echo "Full Proxy Address:socks5://127.0.0.1:$proxyPort"
echo "sshproxy Execute Done..."
sleep 1
nc -w 2 -v 127.0.0.1 $proxyPort
curl --connect-timeout 3 -sS -x socks5://127.0.0.1:$proxyPort 'http://v.ynit.top/ipfull/'
if [[ $noHTTP == false ]]
then
    echo -e "\nNow goProxy convert SOCKS proxy to HTTP:0.0.0.0:$goProxyPort\t Use:127.0.0.1:$goProxyPort"
    #以下为两种运行goproxy转换代理的方式,由bash接收进程信号会导致效率降低,建议直接cmd形式调用
    # way 1: bash run
    #/v/bin/goproxy-for-ssh http -l 0.0.0.0:$goProxyPort -b 127.0.0.1:$proxyPort &>/dev/null &
    # way 2:cmd run
    cmd /c start "GoProxy: HTTP Proxy for $targetHost" `cygpath -w /v/bin/goproxy-for-ssh` http -l 0.0.0.0:$goProxyPort -b 127.0.0.1:$proxyPort
else
    echo -e "\n"
fi

更多使用说明,请运行 sshproxy --help 查看帮助信息


扫描二维码,在手机上阅读!

ssh-expire-time.py:查找~/.ssh/config本月或下月到期主机信息

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#列出~/.ssh/config主机到期时间
#自用ssh-expire-time命令python实现版本
#原始ssh-expire-time为shell脚本实现,参看:/v/bin/ssh-expire-time
import sys
import os
import re
import time

foundCount=0
allHostInfo=[]
allExpireTime=[]

def readHostsInfo(findflag,findNum=None):
    global foundCount
    global allHostInfo
    global allExpireTime
    with open(sshConfigFile,"r") as read_f:
        Tag=False
        findExpire=False
        allHostInfo=[]
        HostInfo=[]
        for num,line in enumerate(read_f.readlines(),1):
            if Tag==True and re.match(r'[ ]*Host ',line,re.I):
                Tag=False
                if findExpire==True:
                    allHostInfo.append(HostInfo)
                    findExpire=False
            if Tag==False and re.match(r'Host .*',line,re.I):
                Tag=True
                HostInfo=[]
                HostInfo.append(line)
                continue
            if Tag==True:
                if re.match(r'.*#[ ]*到期时间.*',line,re.I):
                    findExpire=True
                    if findflag=="all":                         
                        foundCount+=1
                        allExpireTime.append(line)
                    elif findflag=="m":
                        timeRegexp=time.strftime("%Y-%m", time.localtime())
                        timeRegexp=timeRegexp.replace("-0","-0?",1)
                        if not re.match(r'.*'+timeRegexp+'[^0-9]+.*',line,re.I):
                            HostInfo=[]
                            Tag=False
                            findExpire=False
                            continue
                        else:
                            HostInfo.insert(0,line)
                            foundCount+=1
                    elif findflag=="n":
                        nowTime=time.localtime()
                        nowYear=nowTime.tm_year
                        nextMonth=nowTime.tm_mon+1
                        if nextMonth>12:
                            nextMonth=1
                            nowYear+=1
                        nextMonth=str(nextMonth).zfill(2)
                        timeRegexp="{year}-{month}".format(year=nowYear,month=nextMonth)
                        timeRegexp=timeRegexp.replace("-0","-0?",1)
                        if not re.match(r'.*'+timeRegexp+'[^0-9]+.*',line,re.I):
                            HostInfo=[]
                            Tag=False
                            findExpire=False
                            continue
                        else:
                            HostInfo.insert(0,line)
                            foundCount+=1
                HostInfo.append(line)
    return
    
def printUsage():
    print("""
    /v/bin/ssh-expire-time.py
    查询所有主机到期时间,按日期顺序排列
    参数一可附加参数 (month/m) 查看当月到期主机详情;
    参数一可附加参数 (next/n) 查看下月到期主机详情;
    参数二可指定最多列出的主机,缺省为-1,即列出全部匹配主机;
    Example:ssh-expire-time.py m 或 ssh-expire-time.py n;
    Example:ssh-expire-time.py m 2 (匹配两次,只显示到期前两个)  
    """)
    return

sshConfigFile="~/.ssh/config"
sshConfigFile=os.path.expanduser(sshConfigFile)

if len(sys.argv)<2 or (len(sys.argv)==2 and (str(sys.argv[1]).lower()=="--help" or str(sys.argv[1]).lower()=="-h")):
    printUsage()
    readHostsInfo('all')
    if len(allExpireTime)>0:
        allExpireTime.sort(key=None, reverse=False)
        for expireTime in allExpireTime:
            print(expireTime,end="")
    sys.exit(0)
elif len(sys.argv)==2:
    findflag=str(sys.argv[1]).lower()
    findNum=None
elif len(sys.argv)==3:
    findflag=str(sys.argv[1]).lower()
    findNum=int(sys.argv[2])
    
if not (findflag=="m" or findflag=="n"):
    print("参数错误!")
    printUsage()
    sys.exit(0)
    
readHostsInfo(findflag,findNum)
allHostInfo.sort()

suffixText=""
if findNum!=None and findNum<len(allHostInfo):
    allHostInfo=allHostInfo[:findNum]
    suffixText=",显示前 %d 个"%findNum

for Host in allHostInfo:
    Host.pop(0)
    print("".join(Host))
    
if foundCount>1:
    print("共找到主机 %s 个%s"%(foundCount,suffixText))
    
print("\nssh-expire-time.py执行完毕;Python版本:%s"%sys.version)

扫描二维码,在手机上阅读!

sshfindip.py;Python实现命令工具,通过IP或部分ip查找主机信息

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#根据主机ip查找openSSH配置文件~/.ssh/config对应主机配置项
#自用sshfindip命令python实现版本
#原始sshfindip为shell脚本实现,参看:/v/bin/sshfindip
import sys
import os
import re

sshConfigFile="~/.ssh/config"
sshConfigFile=os.path.expanduser(sshConfigFile)

if len(sys.argv)<2 or (len(sys.argv)==2 and (str(sys.argv[1]).lower()=="--help" or str(sys.argv[1]).lower()=="-h")):
    print("""
    /v/bin/sshfindip.py
    使用主机IP或部分IP关键字查找主机配置项信息,查找 ~/.ssh/config 文件内容.
    注:当用不完全IP关键字匹配时,会输出包含此IP关键字的多台主机信息

Usage:
        sshfindip.py [ipstr]
Example:
        sshfindip.py 103.1.1.11
    
    """)
    sys.exit(0)
else:
    ipstr=str(sys.argv[1]).strip()


ipstr=ipstr.replace(".","\.").replace("-","\-")
foundCount=0

with open(sshConfigFile,"r") as read_f:
    Tag=False
    findIp=False
    allHostInfo=[]
    HostInfo=[]
    for num,line in enumerate(read_f.readlines(),1):
        if Tag==True and re.match(r'[ ]*Host ',line,re.I):
            Tag=False
            if findIp==True:
                allHostInfo.append(HostInfo)
                findIp=False
        if Tag==False and re.match(r'Host .*',line,re.I):
            Tag=True
            HostInfo=[]
            HostInfo.append(line)
            continue
        if Tag==True:
            if re.match(r'.*[^#]HostName [ ]*'+ipstr+'.*',line,re.I):
                findIp=True
                foundCount+=1
            HostInfo.append(line)

for Host in allHostInfo:
    print("".join(Host))
    
if foundCount>1:
    print("共找到主机 %s 个"%foundCount)
    
print("\nsshfindip.py 执行完毕;Python版本:%s"%sys.version)

扫描二维码,在手机上阅读!
Title - Artist
0:00