在Linux下通过Docker运行Code Composer Studio

目录 1. CCStudio说明 1.1 软件配置情况 2. 构建镜像 2.1 自动 2.2 手动 3. 运行容器 4. CCStudio组件 5. 其他参考 1. CCStudio说明 Docker镜像可在以下位置获取: Dockerhub: whuzfb/ccstudio GHCR: zfb132/ccstudio 1.1 软件配置情况 目前理论上支持的CCStudio版本: 10.x(已测试版本10.0.0.00010、10.4.0.00006) 11.x(已测试版本11.0.0.00012、11.2.0.00007) 12.x(已测试版本12.0.0.00009、12.8.1.00005) 20.x(已测试版本20.2.0.00012) 支持的Ubuntu版本: ubuntu 20.04及以上版本(已测试版本20.04、22.04、24.04) 支持安装指定版本的mmWave SDK,已测试版本03.06.02.00-LTS 支持安装指定版本的SYS/BIOS,已测试版本6.73.01.01 zfb132/ccstudio目的是提供一个在Linux系统上安装Code Composer Studio的Docker镜像,方便在Linux系统(无桌面环境)上使用CCStudio进行TI芯片的开发,尤其是适用于CI/CD场景。用户也可以参考仓库的configure.sh脚本在自己的Linux系统上安装CCStudio 容器内部最重要的三个目录: /ccs_projects:CCStudio项目目录(运行容器必须挂载本地目录到此目录,因为entrypoint.sh脚本会在此目录下查找项目文件) /workspaces:CCStudio工作空间目录(容器内部CCS的工作空间目录为/workspaces,编译结果也存放在此目录下) /opt/ti:TI系列产品的安装目录(容器内部CCStudio、mmwave SDK、SYS/BIOS的安装目录) 不同版本的CCStudio在Linux系统的安装说明: CCS Linux Host Support CCS Linux Host Support v12 CCS Installation Guide v20 不同版本的CCStudio命令行程序的使用说明: CCS Command Line Interface (v12 and below) CCS Command Line Interface (v20 and above) 2. 构建镜像 2.1 自动 使用make命令自动构建镜像 # 查看可用的目标 make list # 构建指定的镜像 make ubuntu24.04-20.2.0.00012-mmw # 逐个构建镜像 make all # 并行构建镜像(但是输出日志会混在一起) make -j $(nproc) all # 生成docker-compose.yaml文件用于并行构建镜像 make gen_compose # 使用docker-compose构建镜像 docker compose -f docker-compose.yaml --parallel 2 build 2.2 手动 构建镜像的脚本如下: # --network host # --build-arg "HTTP_PROXY=http://127.0.0.1:9900/" \ # --build-arg "HTTPS_PROXY=http://127.0.0.1:9900/" \ # --progress=plain --no-cache # MMWSDK_COMPONENTS或BIOS_VERSION参数若为空,表示不安装对应组件 export UBUNTU_VERSION=24.04 export CCSTUDIO_VERSION=20.2.0.00012 export CCS_COMPONENTS="PF_MMWAVE,PF_C6000SC,PF_TM4C" export MMWSDK_VERSION="03.06.02.00-LTS" export MMWSDK_COMPONENTS="ALL" export BIOS_VERSION="6.73.01.01" # 使用major.minor版本号作为ccstudio版本标识 export CCS_VERSION_SHORT=$(echo ${CCSTUDIO_VERSION} | cut -d '.' -f 1-2) export tag="whuzfb/ccstudio:${CCS_VERSION_SHORT}-ubuntu${UBUNTU_VERSION}" docker build -t ${tag} . \ --build-arg "OS_VERSION=${UBUNTU_VERSION}" \ --build-arg "CCS_VERSION=${CCSTUDIO_VERSION}" \ --build-arg "CCS_COMPONENTS=${CCS_COMPONENTS}" \ --build-arg "MMWSDK_VERSION=${MMWSDK_VERSION}" \ --build-arg "MMWSDK_COMPONENTS=${MMWSDK_COMPONENTS}" \ --build-arg "BIOS_VERSION=${BIOS_VERSION}" 3. 运行容器 从Docker Hub拉取镜像whuzfb/ccstudio: # 拉取最新版本的ccstudio镜像(20.2-ubuntu24.04-mmw) docker pull whuzfb/ccstudio:latest 或者使用本地构建的镜像 挂载本地的ccs项目目录到容器内的/ccs_projects目录下并启动构建: # 假设本地项目目录为 ./mmw_oob git clone --recursive https://github.com/zfb132/mmw_oob.git ./mmw_oob # 该目录下包含out_of_box_6843_isk_mss.projectspec文件,且包含Debug编译配置 # 运行以下命令可以在容器内编译该项目 # 如果需要保存结果,那么使用 -v ./results:/workspaces (容器内部CCS的工作目录为/workspaces) # 默认时区为UTC,可以通过设置 -e TZ=... 来更改时区(例如 -e TZ=Asia/Shanghai) mkdir ./results docker run \ -e TZ=Asia/Shanghai \ -v ./mmw_oob:/ccs_projects \ -v ./results:/workspaces \ -it --rm --name ccstudio whuzfb/ccstudio:latest \ "out_of_box_6843_isk_mss.projectspec" "Debug" 4. CCStudio组件 可安装的产品系列列表: Product family Description OS PF_MSP430 MSP430 ultra-low power MCUs windows-x64, linux-x64, osx PF_MSP432 SimpleLink™ MSP432™ low power + performance MCUs windows-x64, linux-x64, osx PF_CC2X SimpleLink™ CC13xx and CC26xx Wireless MCUs windows-x64, linux-x64, osx PF_CC3X SimpleLink™ Wi-Fi® CC32xx Wireless MCUs windows-x64, linux-x64, osx PF_CC2538 CC2538 IEEE 802.15.4 Wireless MCUs windows-x64, linux-x64, osx PF_C28 C2000 real-time MCUs windows-x64, linux-x64, osx PF_TM4C TM4C12x ARM® Cortex®-M4F core-based MCUs windows-x64, linux-x64, osx PF_PGA PGA Sensor Signal Conditioners windows-x64, linux-x64, osx PF_HERCULES Hercules™ Safety MCUs windows-x64, linux-x64, osx PF_SITARA Sitara™ AM3x, AM4x, AM5x and AM6x MPUs (will also include AM2x for CCS 10.x) windows-x64, linux-x64 PF_SITARA_MCU Sitara™ AM2x MCUs (only supported in CCS 11.x and greater) windows-x64, linux-x64 PF_OMAPL OMAP-L1x DSP + ARM9® Processor windows-x64, linux-x64 PF_DAVINCI DaVinci (DM) Video Processors windows-x64, linux-x64 PF_OMAP OMAP Processors windows-x64, linux-x64 PF_TDA_DRA TDAx Driver Assistance SoCs & Jacinto DRAx Infotainment SoCs windows-x64, linux-x64 PF_C55 C55x ultra-low-power DSP windows-x64, linux-x64 PF_C6000SC C6000 Power-Optimized DSP windows-x64, linux-x64 PF_C66AK_KEYSTONE 66AK2x multicore DSP + ARM® Processors & C66x KeyStone™ multicore DSP windows-x64, linux-x64 PF_MMWAVE mmWave Sensors windows-x64, linux-x64 PF_C64MC C64x multicore DSP windows-x64, linux-x64 PF_DIGITAL_POWER UCD Digital Power Controllers windows-x64, linux-x64 5. 其他参考 zfb132/ccstudio zfb132/mmw_oob uoohyo/ccstudio-ide uoohyo/action-ccstudio-ide ccstudio code composer studio 12.8 and uniflash 8.7 on ubuntu 24.04 codecomposer installing ccs 20.2.0 into a docker container

2025/7/21
articleCard.readMore

Windows电脑配置以太网口访问雷达

目录 1. 总体说明 2. windows电脑配置以太网口 3. 雷达配置ip和网关和路由 4. windows开启路由转发功能 5. windows配置以太网共享无线网络 1. 总体说明 适用情况: 目的只是调试雷达,且当前没有配置好的交换机或路由器 eth1连接到windows电脑的以太网口(此时两者即可互相ping通,可以ssh),还可以通过windows电脑的无线网络让雷达连接到互联网 其中雷达的eth1口配置如下 IP地址示例: 192.168.19.241 子网掩码示例: 255.255.255.0 网关示例: 192.168.19.244(可以自行修改为其他ip,只要与windows电脑的以太网口IP地址一致即可,例如192.168.19.254) windows电脑的以太网口配置如下 IP地址示例: 192.168.19.244(只要与雷达网关一致即可,例如192.168.19.254) 子网掩码示例: 255.255.255.0 网关: 留空 windows电脑可以替换为其他Linux电脑,配置方法类似 2. windows电脑配置以太网口 打开控制面板 -> 网络和Internet -> 网络和共享中心 -> 更改适配器设置 然后再手动修改windows的以太网适配器的IP地址是192.168.19.244(也可以是192.168.19.254),子网掩码是255.255.255.0,保存即可(该适配器可能会显示为未识别的网络,属性信息里面IPv4和IPv6可能会提示无法获取Internet访问权限,这是正常的) 3. 雷达配置ip和网关和路由 # 查看当前网络信息(发现eth1的ip地址是192.168.19.241) ip a # 1: 1o:<L0OPBACK,UP,LOWER UP> mtu 16436 qdisc noqueue state UNKNOWN # link/loopback 00:00:00:00:00:00 brd60:00:00:00:00:00 # inet 127.0.0.1/8 scope host lo # inet6 ::1/128 scope host # valid lft forever preferred lft forever # 2: eth0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc pfifo fast state DOWN qlen 1000 # link/ether 00:0a:aa:aa:aa:aa brd ff:ff:ff:ff:ff:ff # inet 192.168.1.0/24 brd 192.168.1.255 scope global eth0 # 3: eth1: <BROADCAST,MULTICAST,UP,LOWER UP> mtu 1500 qdisc pfifo fast state UNKNOWN qlen 1000 # link/ether 08:1f:ff:ff:ff:ff brd ff:ff:ff:ff:ff:ff # inet 192.168.19.241/24 brd 192.168.19.255 scope global eth1 # inet6 fe80::alf:7lff:fe03:bbc/64 scope link # valid lft forever preferred lft forever # 4: eth2: <BROADCAST,MULTICAST,UP,LOWER UP> mtu 1500 qdisc pfifo fast state UP qlen 1000 # link/ether 00:0b:bb:bb:bb:bb brd ff:ff:ff:ff:ff:ff # inet 172.16.1.0/16 brd 172.16.255.255 scope global eth2 # inet6 fe80::20b:abff:fed3:2b52/64 scope link # valid lft forever preferred lft forever # 查看默认网关(发现eth1的网关是192.168.19.254) route -n # Kernel Ip routing table # Destination Gateway Genmask Flags Metric Ref User Iface # 192.168.19.0 0.0.0.0 255.255.255.0 U 0 0 0 eth1 # 192.168.1.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0 # 172.16.0.0 0.0.0.0 255.255.0.0 U 0 0 0 eth2 # 127.0.0.0 0.0.0.0 255.0.0.0 U 0 0 0 lo # 0.0.0.0 192.168.19.254 0.0.0.0 UG 0 0 0 eth1 如果不想对雷达进行任何修改,则直接把windows电脑的以太网口IP地址修改为192.168.19.254,子网掩码是255.255.255.0,保存即可。雷达会通过eth1口(ip地址是192.168.19.241)经由windows电脑的以太网口(ip地址是192.168.19.254)互相访问。 如果希望自定义雷达的IP和网关,则可以在雷达上执行以下命令: # 切换到root用户(192.168.19.241是自己设置的eth1口IP地址,只要与windows电脑的以太网口IP地址在同一网段即可) ifconfig eth1 192.168.19.241 netmask 255.255.255.0 up # 删除默认网关 route del default # 添加新的默认网关(这里的网关是windows电脑的以太网口IP地址) route add default gw 192.168.19.244 eth1 此时在windows电脑上可以通过ssh连接到雷达: ssh username@192.168.19.241 但是如果想让雷达访问互联网,则需要在windows电脑上开启网络转发功能,并配置以太网共享无线网络。 4. windows开启路由转发功能 修改注册表:以管理员身份打开cmd,输入以下命令 reg add HKLM\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters /v IPEnableRouter /D 1 /f 启动Routing and Remote Access服务:以管理员身份打开cmd,输入以下命令 # 如果报错,就手动去服务中启动 sc config RemoteAccess start=auto sc start RemoteAccess sc query RemoteAccess 5. windows配置以太网共享无线网络 配置共享地址段(防止在共享WLAN给ethernet时,弹出对话框提示以太网的ip地址只能是192.168.137.1) 以管理员身份打开cmd,输入以下命令 reg add "HKLM\SYSTEM\CurrentControlSet\Services\SharedAccess\Parameters" -v ScopeAddress -d 192.168.19.142 -f reg add "HKLM\SYSTEM\CurrentControlSet\Services\SharedAccess\Parameters" -v ScopeAddressBackup -d 192.168.19.142 -f 此处只要ScopeAddress和ScopeAddressBackup的网段是192.168.19.x即可 打开控制面板 -> 网络和Internet -> 网络和共享中心 -> 更改适配器设置 右键点击无线网络连接 -> 属性 -> 共享选项卡 勾选允许其他网络用户通过此计算机的Internet连接来连接,在下拉框中选择以太网(即windows与雷达连接网线后出现的网络适配器),点击确定 此时雷达就可以通过windows电脑的无线网络访问互联网了,直接在雷达上执行以下命令测试: ping baidu.com 关于如何使用frp配置远程访问,参考远程访问安装xfce4的内网服务器

2025/5/26
articleCard.readMore

使用ffmpeg对视频和音频文件进行处理

目录 0. 常用命令说明 1. 倍速播放 1.1 视频画面倍速播放 1.2 音频倍速播放 1.3 视频画面和音频倍速播放 2. 视频片段裁剪 2.1 获取视频的分辨率 2.2 截取指定时长的视频片段 2.3 裁剪视频画面尺寸 3. 视频导出图片 4. 从图片集创建GIF文件 5. 提取视频文件的音频 6. 把音频和画面合并为新的视频 7. 下载m3u8文件为.ts文件 8. 批量提取视频关键帧 0. 常用命令说明 ffmpeg是一个命令行工具,所有的操作都是通过命令行来完成的,下面是一些常用的命令说明 -vcodec codec:强制使用codec编解码方式(copy代表不进行重新编码) -acodec copy:表示音频不做新的编码,直接把原来的复制过来 -vcodec copy:表示视频不做新的编码,直接把原来的复制过来 -threads 5:指定5个线程同时转换 -vn:取消视频的输出 -an:取消音频轨 -ab 160000:设置比特率(单位为bit/s) -ar 8000:设置音频采样率(单位为Hz) -ac 1:设置声道数,1就是单声道,2就是立体声 1. 倍速播放 1.1 视频画面倍速播放 把输入的视频文件,画面播放速度快放到原来的2倍,保存为新的视频文件 ffmpeg -i input.mp4 -filter:v "setpts=0.5*PTS" output.mp4 1.2 音频倍速播放 把输入的视频文件,音频播放速度快放到原来的2倍,保存为新的视频文件 ffmpeg -i input.mp4 -filter:a "atempo=2.0" output.mp4 1.3 视频画面和音频倍速播放 把输入的视频文件,画面播放速度快放到原来的2倍,音频播放速度快放到原来的2倍,保存为新的视频文件 ffmpeg -i input.mp4 -filter_complex "[0:v]setpts=0.5*PTS[v];[0:a]atempo=2.0[a]" -map "[v]" -map "[a]" output.mp4 2. 视频片段裁剪 2.1 获取视频的分辨率 方法一:获取视频的分辨率,以默认分隔符分割 ffprobe -v error -show_entries stream=width,height -of csv=p=0 demo.mp4 1920,1080 方法二:获取视频的分辨率,以x分隔符分割 ffprobe -v error -show_entries stream=width,height -of csv=p=0:s=x output2.mp4 1920x1080 2.2 截取指定时长的视频片段 从视频文件中,截取时间从00:00:00开始到00:00:11之间的片段,输出为新的视频文件 ffmpeg -ss 00:00:00 -to 00:00:11 -i input.mp4 -vcodec copy -acodec copy output.mp4 从视频文件中,截取时间从00:01:00开始,时长00:00:21的片段,输出为新的视频文件 ffmpeg -ss 00:01:00 -t 00:00:21 -i input.mp4 -vcodec copy -acodec copy output2.mp4 从视频文件中,截取时间从00:00:00到00:00:11之间的片段,分辨率为1920x1080,输出为新的视频文件 ffmpeg -ss 00:00:00 -to 00:00:11 -i input.mp4 -vcodec copy -acodec copy -s 1920,1080 output.mp4 2.3 裁剪视频画面尺寸 参数示例:crop=new_width:new_height:start_x:start_y 400x200的新视频,x的起始位置是0(表示从该位置开始,向右400的像素留下),y的起始位置是0(表示从该位置开始,向下200的像素留下)。也就是说,最后留下的视频画面为原视频画面的一部分(以原视频画面的左上顶点为原点) ffmpeg -i input.mp4 -vf crop=400:200:0:0 -threads 5 -preset ultrafast -strict -2 output.mp4 3. 视频导出图片 从视频文件中,以每秒3帧的速率抽取图片,并更改为指定长、宽,最后按照指定命名格式保存 ffmpeg -i demo.mp4 -r 3 -s 1920x1080 -f image2 ./demo-%03d.jpeg 4. 从图片集创建GIF文件 从图片集创建帧率为5的GIF文件 ffmpeg -f image2 -framerate 5 -i ./demo-%03d.jpeg out.gif 5. 提取视频文件的音频 提取视频文件的音频内容保存为mp3格式 ffmpeg -i demo.mp4 -f mp3 -vn -ar 16000 -ac 1 demo.mp3 6. 把音频和画面合并为新的视频 ffmpeg -loglevel quiet -i video.m4s -i audio.m4s -c copy -y out.mp4 7. 下载m3u8文件为.ts文件 ffmpeg -protocol_whitelist file,http,https,tcp,tls -i https://t.cn/a.m3u8 -c copy my_movie.ts 8. 批量提取视频关键帧 #!/bin/bash shopt -s nullglob export video_path="$1" export out_path="$2" export files=(${video_path}/*) # echo ${files[@]} # echo ${#files[@]} for filename in "${files[@]}" do filename="${filename}" export name=$(basename "${filename}") name=${name%.*} echo Converting ${filename} export file_dir="${out_path}/${name}" mkdir "${file_dir}" # 获取视频分辨率(宽,高) # 例如: 1920,1080 # export wh=ffprobe -v error -show_entries stream=width,height -of csv=p=0 "${filename}" # 视频提取语音,方便识别 ffmpeg -y -i "${filename}" -f mp3 -vn -ar 16000 -ac 1 "${file_dir}/audio.mp3" # 视频关键帧提取,方便导出PPT ffmpeg -y -i "${filename}" -vf select='eq(pict_type\,I)' -vsync 2 -s 1920,1080 -f image2 "${file_dir}/keyframe-%03d.png" echo Convert ${filename} successfully! done

2022/12/30
articleCard.readMore

修复Adobe Acrobat打开发票字体显示不全的问题

目录 0. 问题描述 1. 复制系统楷体字体文件 2. 修改字体名称 3. 复制字体文件到Acrobat字体目录 0. 问题描述 Acrobat在2021.005.20060以后的新版本有bug,无法读取楷体GB2312字体,导致打开发票时,发票上的部分中文显示为方框或不显示 1. 复制系统楷体字体文件 文件资源管理器打开C:\Windows\Fonts目录,找到楷体 常规字体文件,即文件C:\Windows\Fonts\simkai.ttf,复制到其他目录,这样不会影响系统正常使用 2. 修改字体名称 使用字体编辑工具FontCreator打开simkai.ttf字体文件,选择Font-Properties打开属性修改,将Family Name修改为KaiTi_GB2312,选择File – Export Font – Export – Export Desktop Font导出字体,可以命名为simkai-new.otf,等待几分钟完成 3. 复制字体文件到Acrobat字体目录 将修改后的字体文件simkai-new.otf复制到C:\Program Files\Adobe\Acrobat DC\Resource\Font目录,重启Acrobat即可

2022/12/28
articleCard.readMore

使用Python代码在Windows资源管理器中定位文件

目录 1. 安装pywin32 2. 脚本文件内容 1. 安装pywin32 pip install pywin32 2. 脚本文件内容 #!/usr/bin/env python # -*- coding: utf-8 -*- # author: 'zfb' # time: 2021-01-06 13:33 import os from pathlib import Path import win32com.shell.shell as shell def launch_file_explorer(file_with_abs_path): ''' 每次弹出文件资源管理器,只能打开一个文件夹,然后(定位)选择一个文件(夹) ''' file = Path(file_with_abs_path) # 对于Linux系统来说 # 如果使用Unity/Gnome桌面,可以使用命令 # nautilus ~/Documents/foo.txt # 对于其他桌面系统,可参考 xdg-open 命令 # 严格按照此格式,不能自己加空格 os.system('explorer.exe /e,/select,"{}"'.format(file)) def launch_files_explorer(path, files): ''' 每次弹出文件资源管理器,只能打开一个文件夹,可以选择多个文件(夹) ''' if len(files) == 0: return path = str(Path(path)) folder_pidl = shell.SHILCreateFromPath(path, 0)[0] desktop = shell.SHGetDesktopFolder() shell_folder = desktop.BindToObject(folder_pidl, None, shell.IID_IShellFolder) name_to_item_mapping = dict([(desktop.GetDisplayNameOf(item, 0), item) for item in shell_folder]) to_show = [] for file in files: if not file in name_to_item_mapping: raise Exception("目录{}下找不到文件{}".format(path, file)) to_show.append(name_to_item_mapping[file]) shell.SHOpenFolderAndSelectItems(folder_pidl, to_show, 0) if __name__ == "__main__": name = os.path.abspath(__file__) path = "D:/github/zfb132.github.com/" names = ["index.html", "README.md", "robots.txt"] launch_file_explorer(name) launch_files_explorer(path, names)

2022/12/27
articleCard.readMore

使用git diff查看不同文件或者不同commit之间的区别

目录 1. 查看不同文件的区别 2. 查看不同commit之间的修改 3. 把diff的转换为html保存 4. ansi2html.sh文件内容 1. 查看不同文件的区别 a.txt和b.txt不在版本控制系统中: git diff --color-words --no-index a.txt b.txt 2. 查看不同commit之间的修改 git diff --color-words HEAD~4 HEAD~3 git diff --color-words ac238c26 5d449a61 3. 把diff的转换为html保存 # 首先安装ansi2html # https://github.com/pixelb/scripts/blob/master/scripts/ansi2html.sh wget "http://www.pixelbeat.org/scripts/ansi2html.sh" -O ansi2html.sh chmod +x ansi2html.sh git diff --color-words HEAD~4 HEAD~3 | ansi2html.sh > docs/diff.html 然后可以用浏览器打开docs/diff.html查看,打印成pdf文件也可以 4. ansi2html.sh文件内容 #!/bin/sh # Convert ANSI (terminal) colours and attributes to HTML # Licence: LGPLv2 # Author: # http://www.pixelbeat.org/docs/terminal_colours/ # Examples: # ls -l --color=always | ansi2html.sh > ls.html # git show --color | ansi2html.sh > last_change.html # Generally one can use the `script` util to capture full terminal output. # Changes: # V0.1, 24 Apr 2008, Initial release # V0.2, 01 Jan 2009, Phil Harnish <philharnish@gmail.com> # Support `git diff --color` output by # matching ANSI codes that specify only # bold or background colour. # P@draigBrady.com # Support `ls --color` output by stripping # redundant leading 0s from ANSI codes. # Support `grep --color=always` by stripping # unhandled ANSI codes (specifically ^[[K). # V0.3, 20 Mar 2009, http://eexpress.blog.ubuntu.org.cn/ # Remove cat -v usage which mangled non ascii input. # Cleanup regular expressions used. # Support other attributes like reverse, ... # P@draigBrady.com # Correctly nest <span> tags (even across lines). # Add a command line option to use a dark background. # Strip more terminal control codes. # V0.4, 17 Sep 2009, P@draigBrady.com # Handle codes with combined attributes and color. # Handle isolated <bold> attributes with css. # Strip more terminal control codes. # V0.26, 16 Nov 2019 # http://github.com/pixelb/scripts/commits/master/scripts/ansi2html.sh gawk --version >/dev/null || exit 1 if [ "$1" = "--version" ]; then printf '0.26\n' && exit fi usage() { printf '%s\n' \ 'This utility converts ANSI codes in data passed to stdin It has 4 optional parameters: --bg=dark --palette=linux|solarized|tango|xterm --css-only|--body-only E.g.: ls -l --color=always | ansi2html.sh --bg=dark > ls.html' >&2 exit } if [ "$1" = "--help" ]; then usage fi processArg() { [ "$1" = "--bg=dark" ] && { dark_bg=yes; return; } [ "$1" = "--css-only" ] && { css_only=yes; return; } [ "$1" = "--body-only" ] && { body_only=yes; return; } if [ "$1" = "--palette=solarized" ]; then # See http://ethanschoonover.com/solarized P0=073642; P1=D30102; P2=859900; P3=B58900; P4=268BD2; P5=D33682; P6=2AA198; P7=EEE8D5; P8=002B36; P9=CB4B16; P10=586E75; P11=657B83; P12=839496; P13=6C71C4; P14=93A1A1; P15=FDF6E3; return; elif [ "$1" = "--palette=solarized-xterm" ]; then # Above mapped onto the xterm 256 color palette P0=262626; P1=AF0000; P2=5F8700; P3=AF8700; P4=0087FF; P5=AF005F; P6=00AFAF; P7=E4E4E4; P8=1C1C1C; P9=D75F00; P10=585858; P11=626262; P12=808080; P13=5F5FAF; P14=8A8A8A; P15=FFFFD7; return; elif [ "$1" = "--palette=tango" ]; then # Gnome default P0=000000; P1=CC0000; P2=4E9A06; P3=C4A000; P4=3465A4; P5=75507B; P6=06989A; P7=D3D7CF; P8=555753; P9=EF2929; P10=8AE234; P11=FCE94F; P12=729FCF; P13=AD7FA8; P14=34E2E2; P15=EEEEEC; return; elif [ "$1" = "--palette=xterm" ]; then P0=000000; P1=CD0000; P2=00CD00; P3=CDCD00; P4=0000EE; P5=CD00CD; P6=00CDCD; P7=E5E5E5; P8=7F7F7F; P9=FF0000; P10=00FF00; P11=FFFF00; P12=5C5CFF; P13=FF00FF; P14=00FFFF; P15=FFFFFF; return; else # linux console P0=000000; P1=AA0000; P2=00AA00; P3=AA5500; P4=0000AA; P5=AA00AA; P6=00AAAA; P7=AAAAAA; P8=555555; P9=FF5555; P10=55FF55; P11=FFFF55; P12=5555FF; P13=FF55FF; P14=55FFFF; P15=FFFFFF; [ "$1" = "--palette=linux" ] && return; fi } processArg #defaults for var in "$@"; do processArg $var; done [ "$css_only" ] && [ "$body_only" ] && usage # Mac OSX's GNU sed is installed as gsed # use e.g. homebrew 'gnu-sed' to get it if ! sed --version >/dev/null 2>&1; then if gsed --version >/dev/null 2>&1; then alias sed=gsed else echo "Error, can't find an acceptable GNU sed." >&2 exit 1 fi fi [ "$css_only" ] || [ "$body_only" ] || printf '%s' "<html> <head> <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"/> <style type=\"text/css\"> pre { white-space: pre-wrap; } " [ "$body_only" ] || printf ".ef0,.f0 { color: #$P0; } .eb0,.b0 { background-color: #$P0; } .ef1,.f1 { color: #$P1; } .eb1,.b1 { background-color: #$P1; } .ef2,.f2 { color: #$P2; } .eb2,.b2 { background-color: #$P2; } .ef3,.f3 { color: #$P3; } .eb3,.b3 { background-color: #$P3; } .ef4,.f4 { color: #$P4; } .eb4,.b4 { background-color: #$P4; } .ef5,.f5 { color: #$P5; } .eb5,.b5 { background-color: #$P5; } .ef6,.f6 { color: #$P6; } .eb6,.b6 { background-color: #$P6; } .ef7,.f7 { color: #$P7; } .eb7,.b7 { background-color: #$P7; } .ef8, .f0 > .bold,.bold > .f0 { color: #$P8; font-weight: normal; } .ef9, .f1 > .bold,.bold > .f1 { color: #$P9; font-weight: normal; } .ef10,.f2 > .bold,.bold > .f2 { color: #$P10; font-weight: normal; } .ef11,.f3 > .bold,.bold > .f3 { color: #$P11; font-weight: normal; } .ef12,.f4 > .bold,.bold > .f4 { color: #$P12; font-weight: normal; } .ef13,.f5 > .bold,.bold > .f5 { color: #$P13; font-weight: normal; } .ef14,.f6 > .bold,.bold > .f6 { color: #$P14; font-weight: normal; } .ef15,.f7 > .bold,.bold > .f7 { color: #$P15; font-weight: normal; } .eb8 { background-color: #$P8; } .eb9 { background-color: #$P9; } .eb10 { background-color: #$P10; } .eb11 { background-color: #$P11; } .eb12 { background-color: #$P12; } .eb13 { background-color: #$P13; } .eb14 { background-color: #$P14; } .eb15 { background-color: #$P15; } " # The default xterm 256 colour palette for red in 0 1 2 3 4 5 ; do for green in 0 1 2 3 4 5 ; do for blue in 0 1 2 3 4 5 ; do c=$((16 + ($red * 36) + ($green * 6) + $blue)) r=$((($red * 40 + 55) * ($red > 0))) g=$((($green * 40 + 55) * ($green > 0))) b=$((($blue * 40 + 55) * ($blue > 0))) [ "$body_only" ] || printf ".ef%d { color: #%2.2x%2.2x%2.2x; } " $c $r $g $b [ "$body_only" ] || printf ".eb%d { background-color: #%2.2x%2.2x%2.2x; }\n" $c $r $g $b done done done for gray in $(seq 0 23); do c=$(($gray+232)) l=$(($gray*10 + 8)) [ "$body_only" ] || printf ".ef%d { color: #%2.2x%2.2x%2.2x; } " $c $l $l $l [ "$body_only" ] || printf ".eb%d { background-color: #%2.2x%2.2x%2.2x; }\n" $c $l $l $l done [ "$body_only" ] || printf '%s' ' .f9 { color: '`[ "$dark_bg" ] && printf "#$P7;" || printf "#$P0;"`' } .b9 { background-color: #'`[ "$dark_bg" ] && printf $P0 || printf $P15`'; } .f9 > .bold,.bold > .f9, body.f9 > pre > .bold { /* Bold is heavy black on white, or bright white depending on the default background */ color: '`[ "$dark_bg" ] && printf "#$P15;" || printf "#$P0;"`' font-weight: '`[ "$dark_bg" ] && printf 'normal;' || printf 'bold;'`' } .reverse { /* CSS does not support swapping fg and bg colours unfortunately, so just hardcode something that will look OK on all backgrounds. */ '"color: #$P0; background-color: #$P7;"' } .underline { text-decoration: underline; } .line-through { text-decoration: line-through; } .blink { text-decoration: blink; } /* Avoid pixels between adjacent span elements. Note this only works for lines less than 80 chars where we close span elements on the same line. span { display: inline-block; } */ ' [ "$body_only" ] || [ "$css_only" ] && printf '%s\n' \ 'To use the css generated from --css-only, do: '\ '<head><link rel="stylesheet" type="text/css" href="style.css"></head>' >&2 [ "$css_only" ] && exit [ "$body_only" ] || printf '%s' '</style> </head> <body class="f9 b9"> <pre> ' [ "$body_only" ] && printf '%s\n' 'Be sure to use <body class="f9 b9"> and <pre>' >&2 p='\x1b\[' #shortcut to match escape codes # Handle various xterm control sequences. # See /usr/share/doc/xterm-*/ctlseqs.txt sed " # escape ampersand and quote s#&#\&amp;#g; s#\"#\&quot;#g; s#\x1b[^\x1b]*\x1b\\\##g # strip anything between \e and ST s#\x1b][0-9]*;[^\a]*\a##g # strip any OSC (xterm title etc.) s#\r\$## # strip trailing \r # strip other non SGR escape sequences s#[\x07]##g s#\x1b[]>=\][0-9;]*##g s#\x1bP+.\{5\}##g # Mark cursor positioning codes \"Jr;c; s#${p}\([0-9]\{1,2\}\)G#\"J;\1;#g s#${p}\([0-9]\{1,2\}\);\([0-9]\{1,2\}\)H#\"J\1;\2;#g # Mark clear as \"Cn where n=1 is screen and n=0 is to end-of-line s#${p}H#\"C1;#g s#${p}K#\"C0;#g # Mark Cursor move columns as \"Mn where n is +ve for right, -ve for left s#${p}C#\"M1;#g s#${p}\([0-9]\{1,\}\)C#\"M\1;#g s#${p}\([0-9]\{1,\}\)D#\"M-\1;#g s#${p}\([0-9]\{1,\}\)P#\"X\1;#g s#${p}[0-9;?]*[^0-9;?m]##g " | # Normalize the input before transformation sed " # escape HTML (ampersand and quote done above) s#>#\&gt;#g; s#<#\&lt;#g; # handle truecolor s#${p}38;2;\([0-9]\{1,3\}\);\([0-9]\{1,3\}\);\([0-9]\{1,3\}\)m#\ <span style=\"color:rgb(\1\,\2\,\3\)\">#g s#${p}48;2;\([0-9]\{1,3\}\);\([0-9]\{1,3\}\);\([0-9]\{1,3\}\)m#\ <span style=\"background-color:rgb(\1\,\2\,\3\)\">#g # normalize SGR codes a little # split 256 colors out and mark so that they're not # recognised by the following 'split combined' line :e s#${p}\([0-9;]\{1,\}\);\([34]8;5;[0-9]\{1,3\}\)m#${p}\1m${p}¬\2m#g; t e s#${p}\([34]8;5;[0-9]\{1,3\}\)m#${p}¬\1m#g; :c s#${p}\([0-9]\{1,\}\);\([0-9;]\{1,\}\)m#${p}\1m${p}\2m#g; t c # split combined s#${p}0\([0-7]\)#${p}\1#g #strip leading 0 s#${p}1m\(\(${p}[4579]m\)*\)#\1${p}1m#g #bold last (with clr) s#${p}m#${p}0m#g #add leading 0 to norm # undo any 256 color marking s#${p}¬\([34]8;5;[0-9]\{1,3\}\)m#${p}\1m#g; # map 16 color codes to color + bold s#${p}9\([0-7]\)m#${p}3\1m${p}1m#g; s#${p}10\([0-7]\)m#${p}4\1m${p}1m#g; # change 'reset' code to \"R s#${p}0m#\"R;#g " | # Convert SGR sequences to HTML sed " # common combinations to minimise html (optional) :f s#${p}3[0-7]m${p}3\([0-7]\)m#${p}3\1m#g; t f :b s#${p}4[0-7]m${p}4\([0-7]\)m#${p}4\1m#g; t b s#${p}3\([0-7]\)m${p}4\([0-7]\)m#<span class=\"f\1 b\2\">#g s#${p}4\([0-7]\)m${p}3\([0-7]\)m#<span class=\"f\2 b\1\">#g s#${p}1m#<span class=\"bold\">#g s#${p}4m#<span class=\"underline\">#g s#${p}5m#<span class=\"blink\">#g s#${p}7m#<span class=\"reverse\">#g s#${p}9m#<span class=\"line-through\">#g s#${p}3\([0-9]\)m#<span class=\"f\1\">#g s#${p}4\([0-9]\)m#<span class=\"b\1\">#g s#${p}38;5;\([0-9]\{1,3\}\)m#<span class=\"ef\1\">#g s#${p}48;5;\([0-9]\{1,3\}\)m#<span class=\"eb\1\">#g s#${p}[0-9;]*m##g # strip unhandled codes " | # Convert alternative character set and handle cursor movement codes # Note we convert here, as if we do at start we have to worry about avoiding # conversion of SGR codes etc., whereas doing here we only have to # avoid conversions of stuff between &...; or <...> # # Note we could use sed to do this based around: # sed 'y/abcdefghijklmnopqrstuvwxyz{}`~/▒␉␌␍␊°±␤␋┘┐┌└┼⎺⎻─⎼⎽├┤┴┬│≤≥π£◆·/' # However that would be very awkward as we need to only conv some input. # The basic scheme that we do in the awk script below is: # 1. enable transliterate once "T1; is seen # 2. disable once "T0; is seen (may be on diff line) # 3. never transliterate between &; or <> chars # 4. track x,y movements and active display mode at each position # 5. buffer line/screen and dump when required sed " # change 'smacs' and 'rmacs' to \"T1 and \"T0 to simplify matching. s#\x1b(0#\"T1;#g; s#\x0E#\"T1;#g; s#\x1b(B#\"T0;#g s#\x0F#\"T0;#g " | ( gawk ' function dump_line(l,del,c,blanks,ret) { for(c=1;c<maxX;c++) { if ((c SUBSEP l) in attr || alength(cur)) { ret = ret blanks fixas(cur,attr[c,l]) if(del) delete attr[c,l] blanks="" } if ((c SUBSEP l) in dump) { ret=ret blanks dump[c,l] if(del) delete dump[c,l] blanks="" } else blanks=blanks " " } if(alength(cur)) ret=ret blanks return ret } function dump_screen(l,ret) { for(l=1;l<=maxY;l++) ret=ret dump_line(l,0) "\n" return ret fixas(cur, "") } function atos(a,i,ret) { for(i=1;i<=alength(a);i++) if(i in a) ret=ret a[i] return ret } function alength(a, i, k) { k = 0 for(i in a) k++ return k } function fixas(a,s,spc,i,attr,rm,ret) { spc=alength(a) l=split(s,attr,">") for(i=1;i<=spc;i++) { rm=rm?rm:(a[i]!=attr[i]">") if(rm) { ret=ret "</span>" delete a[i]; } } for(i=1;i<l;i++) { attr[i]=attr[i]">" if(a[i]!=attr[i]) { a[i]=attr[i] ret = ret attr[i] } } return ret } function encode(string,start,end,i,ret,pos,sc,buf) { if(!end) end=length(string); if(!start) start=1; state=3 for(i=1;i<=length(string);i++) { c=substr(string,i,1) if(state==2) { sc=sc c if(c==";") { c=sc state=last_mode } else continue } else { if(c=="\r") { x=1; continue } if(c=="<") { # Change attributes - store current active # attributes in span array split(substr(string,i),cord,">"); i+=length(cord[1]) span[++spc]=cord[1] ">" continue } else if(c=="&") { # All goes to single position till we see a semicolon sc=c state=2 continue } else if(c=="\b") { # backspace move insertion point back 1 if(spc) attr[x,y]=atos(span) x=x>1?x-1:1 continue } else if(c=="\"") { split(substr(string,i+2),cord,";") cc=substr(string,i+1,1); if(cc=="T") { # Transliterate on/off if(cord[1]==1&&state==3) last_mode=state=4 if(cord[1]==0&&state==4) last_mode=state=3 } else if(cc=="C") { # Clear if(cord[1]+0) { # Screen - if Recording dump screen if(dumpStatus==dsActive) ret=ret dump_screen() dumpStatus=dsActive delete dump delete attr x=y=1 } else { # To end of line for(pos=x;pos<maxX;pos++) { dump[pos,y]=" " if (!spc) delete attr[pos,y] else attr[pos,y]=atos(span) } } } else if(cc=="J") { # Jump to x,y i+=length(cord[2])+1 # If line is higher - dump previous screen if(dumpStatus==dsActive&&cord[1]<y) { ret=ret dump_screen(); dumpStatus=dsNew; } x=cord[2] if(length(cord[1]) && y!=cord[1]){ y=cord[1] if(y>maxY) maxY=y # Change y - start recording dumpStatus=dumpStatus?dumpStatus:dsReset } } else if(cc=="M") { # Move left/right on current line x+=cord[1] } else if(cc=="X") { # delete on right for(pos=x;pos<=maxX;pos++) { nx=pos+cord[1] if(nx<maxX) { if((nx SUBSEP y) in attr) attr[pos,y] = attr[nx,y] else delete attr[pos,y] if((nx SUBSEP y) in dump) dump[pos,y] = dump[nx,y] else delete dump[pos,y] } else if(spc) { attr[pos,y]=atos(span) dump[pos,y]=" " } } } else if(cc=="R") { # Reset attributes while(spc) delete span[spc--] } i+=length(cord[1])+2 continue } else if(state==4&&i>=start&&i<=end&&c in Trans) c=Trans[c] } if(dumpStatus==dsReset) { delete dump delete attr ret=ret"\n" dumpStatus=dsActive } if(dumpStatus==dsNew) { # After moving/clearing we are now ready to write # somthing to the screen so start recording now ret=ret"\n" dumpStatus=dsActive } if(dumpStatus==dsActive||dumpStatus==dsOff) { dump[x,y] = c if(!spc) delete attr[x,y] else attr[x,y] = atos(span) if(++x>maxX) maxX=x; } } # End of line if dumping increment y and set x back to first col x=1 if(!dumpStatus) return ret dump_line(y,1); else if(++y>maxY) maxY=y; return ret } BEGIN{ OFS=FS # dump screen status dsOff=0 # Not dumping screen contents just write output direct dsNew=1 # Just after move/clear waiting for activity to start recording dsReset=2 # Screen cleared build new empty buffer and record dsActive=3 # Currently recording F="abcdefghijklmnopqrstuvwxyz{}`~" T="▒␉␌␍␊°±␤␋┘┐┌└┼⎺⎻─⎼⎽├┤┴┬│≤≥π£◆·" maxX=80 delete cur; x=y=1 for(i=1;i<=length(F);i++)Trans[substr(F,i,1)]=substr(T,i,1); } { $0=encode($0) } 1 END { if(dumpStatus) { print dump_screen(); } }' ) [ "$body_only" ] || printf '</pre> </body> </html>\n'

2022/12/27
articleCard.readMore

SRT字幕文件转文本文件

目录 1. 获取字幕文件 2. python脚本 1. 获取字幕文件 一般来说,很多视频网站都会提供视频的字幕文件。有的可以直接下载,有的需要先下载视频,然后再使用字幕软件提取字幕文件。还有一些可以在Chrome浏览器中安装字幕插件,然后在视频播放页面中直接下载字幕文件。总而言之,需要先获取到字幕文件,然后才能进行下一步操作。SRT格式的字幕文件是最常见的,其格式如下所示: 1 2 3 4 5 6 7 1 00:00:00,000 --> 00:00:02,000 Life is short 2 00:00:02,205 --> 00:00:04,000 You need Python 可以看到,字幕文件由多个字幕组成,每个字幕由两行组成,第一行是字幕的序号,第二行是字幕的时间轴,第三行是字幕的内容。字幕之间用空行分隔。所以,只需要先删除所有空行,然后对line_num%3==0的行进行处理,即可得到字幕的内容 2. python脚本 文件内容如下: #!/usr/bin/env python # -*- coding: utf-8 -*- # author: 'zfb' # time: 2019-10-26 17:17 import argparse import glob import os # 输出文件的头部信息,可以为空 header = "zfb 2019-10-26 17:17\n\n" # 段落开始符号 begin_para_symbol = " " # 拼接句子的符号 split_line_symbol = "," # 拼接字幕文件的符号 split_file_symbol = "\n\n\n" def read_toc(file_name): with open(file_name, "r", encoding="utf8") as file: lines = file.readlines() # 去除所有空行 strip_lines = [line.strip()+"\n" for line in lines if len(line.strip())] return strip_lines def read_srt(file_name): with open(file_name, "r", encoding="utf8") as file: lines = file.readlines() # 去除所有空行 strip_lines = [line.strip() for line in lines if len(line.strip())] # 根据文件格式,字幕文字所在行是3的倍数,从起始位置,到结束位置,间隔为3 text_lines = strip_lines[2::3] # 按照逗号拼接全文 text = split_line_symbol.join(text_lines) return text def get_files(directory): # 按文件名排序 return sorted(glob.glob(os.path.join(directory, "*.srt"))) def convert(srt_files, toc_lines, txt_name): content = header for i in range(len(srt_files)): content = content + toc_lines[i] + begin_para_symbol + read_srt(srt_files[i]) + split_file_symbol with open(txt_name, "w") as file: file.write(content) if __name__ == "__main__": parser = argparse.ArgumentParser( description='SRT字幕文件转TXT文件', formatter_class=argparse.RawDescriptionHelpFormatter, epilog= '''\ 用法示例: python srt2txt.py ./srt/ ./content.txt -t ./toc.txt python srt2txt.py ./srt/ ./content.txt python srt2txt.py ''' ) # 可选参数 parser.add_argument( "-s", "--srt_dir", type=str, default="./srt/", help="*.srt字幕文件所在目录,默认为当前目录下的srt文件夹" ) parser.add_argument( "-o", "--output_name", type=str, default="./content.txt", help="输出文件名,默认为content.txt" ) parser.add_argument( "-t", "--toc", type=str, default="./toc.txt", help="目录文件名,默认为toc.txt, 如果没有,会根据字幕文件名生成" ) args = parser.parse_args() # 字幕文件所在目录 srt_file_path = args.srt_dir # 目录文件,如果没有,会根据字幕文件名生成 toc_file = args.toc # 输出文件 txt_file = args.output_name files = get_files(srt_file_path) if os.path.exists(toc_file): # 读取目录文件 toc_lines = read_toc(toc_file) else: # 根据srt文件名,生成目录文件 toc_lines = [os.path.basename(file) + "\n" for file in files] convert(files, toc_lines, txt_file)

2022/12/27
articleCard.readMore

在ubuntu系统安装配置heatererp软件

目录 1. 下载软件包并安装依赖 2. 配置heatererp 3. 创建文件夹保存运算结果 4. 运行测试 5. 注意 1. 下载软件包并安装依赖 安装需要依赖的软件,使用nec2c虽然运行慢,但是配置简单 sudo apt-get install zip nec2c octave https://gitlab.com/andrewsenior/heatererp 2. 配置heatererp 启动heatererp,步骤如下: cd ~/heatererp-master/bin chmod +x ./erpmodel.sh ./erpmodel.sh ~/.config/heatererp/conf.m文件中的路径 conf.m的内容如下,注意model_engine设置为nec2c % Configuration script for Heater ERP model model_dir='/home/zfb/heatererp-master/models'; nec2_bin='/the/real/path/to/nec2'; nec2c_bin='nec2c'; model_engine='nec2c'; log_dir='/home/zfb/heatererp/logs'; results_dir='/home/zfb/heatererp/results'; plots_dir='/home/zfb/heatererp/plots'; 3. 创建文件夹保存运算结果 创建的文件夹要与conf.m文件中设置的相对应 cd ~ && mkdir heatererp && cd heatererp mkdir logs plots results 4. 运行测试 放置log文件,执行sh脚本运行模型 cp ~/heatererp-master/testing/1970-01-01_tx.log ~/heatererp/logs/ cd ~/heatererp-master/bin && ./erpmodel.sh erpmodel('01-Jan-1970 00:00:00');erpmodel('01-Jan-1970 01:28:00'); 等待运行结束,在/home/zfb/heatererp/对应文件夹寻找结果 5. 注意 在Ubuntu 18.04系统测试通过(Ubuntu 20.04好像不太行) 如果系统有GUI,还会同时显示图片 .log文件的第一行是实验开始时间,erpmodel()的参数可以是那个时刻及以后的时刻

2021/2/27
articleCard.readMore

在linux系统监控某个程序的执行情况并通知用户

目录 介绍 代码 运行监控代码文件 介绍 如果有一个下载任务需要执行(python3 download.py),该任务会下载许多文件,一般将其放在后台执行。但是又需要知道它是否在某个时刻退出,可能是因为: 任务执行完毕,正常结束运行 任务异常退出,可能由于下载的网站爬虫策略限制,也可能是其他原因 无论由于哪个原因,一旦程序停止,都需要立刻用户,所以编写以下代码来实现该功能 代码 使用python语言编写监控程序detect.py文件: 如果需要使用腾讯云发送短信通知,则安装库qcloudsms_py 如果需要使用twilio发送短信通知,则安装库twilio 文件内容如下: #!/usr/bin/env python # -*- coding: utf-8 -*- # author: 'zfb' # time: 19-06-29 09:52 import datetime import json import os import requests import socket import logging from logging.handlers import RotatingFileHandler from qcloudsms_py import SmsSingleSender from qcloudsms_py.httpclient import HTTPError LOG_FORMAT = "%(asctime)s [%(funcName)s: %(filename)s,%(lineno)d] - %(levelname)s : %(message)s" DATE_FORMAT = "%m/%d/%Y %H:%M:%S" LOG_PATH = "./log/" # 初始化日志文件配置 def initLog(fileName,logger): # 创建日志文件夹 if not os.path.exists(LOG_PATH): os.mkdir(LOG_PATH) myapp = logging.getLogger(logger) myapp.setLevel(logging.DEBUG) # 切割日志文件 handler = RotatingFileHandler(LOG_PATH+fileName, maxBytes=128*1024, backupCount=60) handler.setFormatter(logging.Formatter(LOG_FORMAT,DATE_FORMAT)) myapp.addHandler(handler) return myapp logging = initLog('detect.log', 'detect') # ------------ 使用腾讯云发送短信通知用户 ----------- APP_ID = 1412345678 APP_KEY = "3998d59614123456789b72dd5961405c" TEMPLATE_ID = 101234 SMS_SIGN = "签名A" # ------------ 使用腾讯云发送短信通知用户 ----------- # ------------ 使用twilio发送短信 ------------------ SMS_SID = 'ACb770c5f63aac91c44d97891234567890' SMS_TOKEN = '42b1294966799e965883181234567890' SMS_FROM_NUMBER = '+12512123456' # ------------ 使用twilio发送短信 ------------------ # ------------ 使用邮箱发信 ------------------------ EMAIL_FROM = 'example@qq.com' EMAIL_PWD = '123demo' # ------------ 使用邮箱发信 ------------------------ def sendSMS(number, params, app_id=APP_ID, key=APP_KEY, template_id=TEMPLATE_ID, sms_sign=SMS_SIGN): ssender = SmsSingleSender(app_id, key) try: result = ssender.send_with_param(86, number, template_id, params, sign=sms_sign, extend="", ext="") except HTTPError as e: log = json.dumps(e, ensure_ascii=False) logging.error(log) print(log) except Exception as e: log = json.dumps(e, ensure_ascii=False) logging.error(log) print(log) log = json.dumps(result, ensure_ascii=False) logging.debug(log) print(log) # 使用twilio的使用账户发送短信 def send_sms(phone, content): from twilio.rest import Client # 账户信息: twilio.com/console account_sid = SMS_SID auth_token = SMS_TOKEN from_phone_num = SMS_FROM_NUMBER client = Client(account_sid, auth_token) message = client.messages.create(body=content, from_=from_phone_num, to=phone) print(message.sid) # 使用139邮箱的短信通知功能 def send_email(email, subject, msg): from smtplib import SMTPException, SMTP_SSL from email.mime.text import MIMEText from email.header import Header # 发件人 sender = EMAIL_FROM pwd = EMAIL_PWD # 三个参数:第一个为文本内容,第二个为plain设置文本格式,第三个为utf-8设置编码 message = MIMEText(msg,"plain",'utf-8') message ['From'] = Header(sender,'utf-8') message ['To'] = Header(email,'utf-8') message["Subject"] = Header(subject,"utf-8") try: # 使用非本地服务器,需要建立ssl连接 smtpObj = SMTP_SSL("smtp.exmail.qq.com", 465) smtpObj.login(sender,pwd) smtpObj.sendmail(sender,email,message.as_string()) print("邮件发送成功") except SMTPException as e: print("Error:无法发送邮件.Case:%s"%e) # 检测下载进程是否正在运行 def isRunning(search_param): output = os.popen('ps -ef | grep {}'.format(search_param)) length = 0 for line in output: # print(line) if "/bin/sh" in line or "grep" in line or "Terminated" in line: continue length = length + 1 # print(length) return True if length > 0 else False # 获取系统用户名和ip def getInfomation(): user = socket.gethostname() # 创建socket访问DNS来获取本机的IP,如果是NAT的话,则是局域网IP local_ip = "127.0.0.1" try: s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) s.connect(('1.1.1.1', 80)) local_ip = s.getsockname()[0] finally: s.close() # 访问www.ip.cn网站获取公网IP net_ip = "127.0.0.1" try: net_ip = requests.get('https://api.ipify.org').text finally: pass return (user, local_ip, net_ip) if __name__ == "__main__": status = isRunning("download.py") flag_file = "/home/ubuntu/flag" # now = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") if status: logging.debug("program is running") else: if os.path.isfile(flag_file): logging.error("program stopped, nobody fixed it.") else: info = getInfomation() msg = "您的主机{},公网IP地址为{},局域网IP为{},下载进程已中断".format(info[0], info[2], info[1]) phone = "13612345678" sendSMS(phone, ['spy', msg]) send_sms(phone, msg) send_email("user@qq.com", "spy", msg) with open(flag_file, "w+") as file: file.write("Please delete me after restarting the download program.") logging.error("program stopped") 运行监控代码文件 在终端输入crontab -e打开定时管理任务,然后在文件中最后添加一行,内容如下: */30 * * * * python3 /home/ubuntu/detect.py 注意:每次重新启动下载进程之后,务必删除flag文件(为了防止因为没有及时重启下载进程而浪费短信资源,在主目录~下输入rm flag即可删除此文件)

2021/2/11
articleCard.readMore

在linux系统使用expect命令自动填充ssh或scp等命令的密码

目录 expect命令使用范例 expect命令使用范例 shell脚本文件的名称为download.sh,内容如下: #!/usr/bin/env bash # 任何一句命令执行出错,都会终止该脚本 set -e # 设置为调试模式,在执行过程中会同时输出各变量的值 # set -x # 连接scp ####################### # expect { # -re ".*es.*o.*" { # exp_send "yes\r" # exp_continue # } # -re ".*sword.*" { # exp_send "mypwd12345\r" # } # } # 把远程机器上的文件下载到本地机器 # 参数1: 远程机器上的文件(或文件夹)的绝对路径 # 参数2: 存放位置,即本地机器上的文件夹 # 当scp下载大文件时,需要耗费更多时间,设置timeout function scp_download(){ src=$1 dst=$2 if [ $# -eq 2 ] then need_ssh=0 else need_ssh=$3 fi name=zfb host="192.168.1.56" passwd="1234567890pwd" if [ $3 -eq 1 ] then # ssh登录远程机器,为目标文件添加读写执行权限 /usr/bin/expect<<EOF spawn ssh $name@$host expect { -timeout -1 "*yes/no" { send "yes\r";exp_continue } "*password:" { send "$passwd\r" # zfb@my-Server:~$ expect "~.*$" send "sudo chmod 777 $src\r" expect "*assword:" send "$passwd\r" expect "~.*$" send "exit\r" expect eof } } EOF fi # 使用scp自动下载文件 /usr/bin/expect<<EOF set timeout 600 spawn scp -r $name@$host:$src $dst expect { "*yes/no" { send "yes\r";exp_continue } "*password:" { send "$passwd\r" expect eof } } EOF } # 脚本运行参数 # 参数1: 远程机器的文件(夹)绝对路径, 例如 /media/data/test/a.txt # 参数2:保存位置,即本地路径 # 若本地不存在,则创建目录 if [ ! -d $2 ] then echo $2" does not exist, ready to mkdir "$2 mkdir -p $2 echo "mkdir successfully!" fi data=$2/opendata if [ ! -d $data ] then echo $data" does not exist, ready to mkdir "$data mkdir -p $data echo "mkdir successfully!" fi scp_download $1/test.txt $2 scp_download $1/test/testaa.py $2 mv $2/testaa.py $2/testbb.py scp_download $1/test/opendata/testcc.txt $data # testdd.txt在远程机器上,无读取权限,需要ssh进行chmod添加权限 scp_download $1/test/opendata/testdd.txt $data 1 使用方法示例: ./download.sh /media/data/test ./

2021/1/16
articleCard.readMore