shell_util

1 模块简介

xlib/util/shell_util.py

用于在 butterfly 中执行 shell 命令

备注:此模块可独立使用

2 使用

2.1 butterfly 中使用例子

2.1.1 进入 butterfly 主目录

cd butterfly

备注:butterfly 主目录为 run.sh 所在的目录

2.1.2 创建 shell app

mkdir -p handlers/shell

2.1.3 编写 handler

将如下代码写入 handlers/shell/__init__.py

2.1.4 启动 butterfly

启动

或者

重启

2.1.5 请求

2.2 自己脚本调用此库

执行日志

3 其他实践

3.1 在远程服务器上执行本地带参数的 shell 脚本

3.1.1 操作例子

假如需要 kill 进程,则需要过滤到脚本,ps 命令等

远端执行脚本

3.1.2 常见错误

3.2 subprocess.Popen().poll() 返回值详解

poll 函数返回码:

  • 0 正常结束

  • 1 sleep

  • 2 子进程不存在

  • -15 kill

3.3 Popen 僵尸进程

ceshi.sh

  • python(父进程)用 subprocess.Popen 新建一个进程(子进程)去开启一个 shell

  • shell 新开一个子进程(孙进程)去执行 ping 127.0.0.1 的命令

这个时候 process.communicate() 是阻塞的

3.4 使用 timer 控制超时时间

  • 问题

    • 如果遇到 kill 导致僵尸进程,父进程则会阻塞到 process.communicate() 这里

3.5 检查机器是否存活

3.6 容器相关

3.6.1 登录容器

sshx.exp(模拟用户与应用程序的交互)

command 命令

3.6.2 通过 docker_exec.sh 对容器发起命令

docker_exec.sh

docker 参数

  • 脚本中不能加 -it 参数,否则会返回 the input device not a TTY 错误

shell ${*:2}:从第二个位置参数开始,将所有剩余的位置参数视为一个单一的字符串

  • 在没有双引号包裹时,$*与 $@相同:都是数组

  • 被双引号包裹时,$*与 $@不同:"$@"为数组,"$*"为一个字符串,SHELL会将所有参数整合为一个字符串。

$*与 $@ 区别(执行./script.sh arg1 arg2 arg3)

代码
返回
说明

#!/bin/bash

for arg in "${*:2}"; do echo "$arg" done

arg2 arg3

${*:2}被扩展成了单个字符串arg2 arg3

#!/bin/bash

for arg in "${@:2}"; do echo "$arg" done

arg2 arg3

${@:2}将每个剩余的位置参数作为独立的引用字符串进行迭代

command 命令(如查询容器里是否有 gcc 12)

3.6.3 通过登录机器对容器发起命令

本质上和 3.6.2 一样,只是改为了自定义的脚本,对容器进行发送命令

如清理 /var/spool/postfix/maildrop 脚本

3.6.4 容器超时

现象:

仅使用 shell_util 超时执行 /home/work/scripts/sshpass -p <password> ssh root@<IP> 'bash -s' <SHELL_FILE> 时,到超时时间之后

shell_util 中的 process.terminate 并没有效果

  • 【执行机器】上会存在 sshpass 的进程,以及 ssh root@<IP> 的子进程

  • 【远端机器】上会存在 docker exec 相关进程

  • 【容器内部】 上会存在容器要执行的命令

3.7 远程执行脚本,含横杠开头参数

问题原因

SSH 客户端会按以下方式解析:

  1. < xx.sh 将脚本内容通过 stdin 传递给远程的 bash -s

  2. -r bj 被误认为是 SSH 客户端的本地参数,而非远程命令参数

最终远程执行的命令实际是:

解决方案

需要通过 -- 显式分隔本地参数和远程参数:

正确命令:

或:

关键点解释

  1. -- 的作用 告诉 SSH 客户端后续参数 (-r bj) 属于远程命令,而非本地 SSH 参数。

  2. bash -s 的机制 -s 表示从 stdin 读取脚本,后续参数会传递给脚本本身(即 $1 对应 -r$2 对应 bj)。

3.8 Redis 4c 绑核脚本

程序中的判断 xxx|| exit -1 可以封装函数代替 exit -1,输出内容并进行退出

Last updated