├── linux-systemctl-template ├── env │ └── env ├── system │ └── conf └── ser.sh ├── linux-socat-forward └── port-forward.sh ├── LICENSE ├── linux-screen-tool └── screen-tool.sh ├── linux-user-manager └── user-manager.sh ├── linux-terminal-clipboard └── terminal-clipboard.sh ├── README.md └── linux-firewall └── firewall-cui.sh /linux-systemctl-template/env/env: -------------------------------------------------------------------------------- 1 | EXAMPLE_ENV_1=aaa 2 | EXAMPLE_ENV_2=bbb -------------------------------------------------------------------------------- /linux-socat-forward/port-forward.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # 参数说明: 4 | # $1 = BIND_PORT (本地监听端口) 5 | # $2 = REMOTE_IP (远程目标IP) 6 | # $3 = REMOTE_PORT (远程目标端口) 7 | 8 | # 检查必需参数是否定义 9 | if [ -z "$1" ]; then 10 | echo "BIND_PORT not defined" 11 | exit 1 12 | elif [ -z "$2" ]; then 13 | echo "REMOTE_IP not defined" 14 | exit 1 15 | elif [ -z "$3" ]; then 16 | echo "REMOTE_PORT not defined" 17 | exit 1 18 | fi 19 | 20 | # 执行端口转发 21 | socat "TCP-LISTEN:$1,fork,reuseaddr" "TCP:$2:$3" -------------------------------------------------------------------------------- /linux-systemctl-template/system/conf: -------------------------------------------------------------------------------- 1 | ;安装 2 | 3 | [Unit] 4 | ;描述,非必须 5 | ;Description="" 6 | 7 | ;在网络启动后才执行该脚本。除非有啥依赖,一般不用改。 8 | After=network.target 9 | 10 | [Service] 11 | 12 | ;simple 用于执行程序会导致阻塞情况 13 | ;forking 用于执行程序会不会阻塞情况 14 | Type=simple 15 | ;Type=forking 16 | 17 | ;以什么用户来启动,非必须 18 | ;User=root 19 | 20 | ;程序工作路径 21 | WorkingDirectory=/your/workdir/path 22 | 23 | ;程序路径 24 | ExecStart=echo ${EXAMPLE_ENV_1} 25 | 26 | ;程序restart时执行,非必须 27 | ;ExecReload= 28 | 29 | ;程序stop时执行,非必须 30 | ;ExecStop= 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 2-Clause License 2 | 3 | Copyright (c) 2025, hvhghv 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this 9 | list of conditions and the following disclaimer. 10 | 11 | 2. Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | 15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 19 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 21 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 22 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 23 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 24 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | -------------------------------------------------------------------------------- /linux-systemctl-template/ser.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # 获取 ./system/ 目录中的第一个文件 4 | shopt -s nullglob 5 | system_files=(./system/*) 6 | shopt -u nullglob 7 | 8 | # 检查目录下是否有文件 9 | if [ ${#system_files[@]} -eq 0 ]; then 10 | echo "Error: No files found in ./system/" 11 | exit 1 12 | fi 13 | 14 | # 提取文件名(不含路径和后缀) 15 | filename=$(basename -- "${system_files[0]}") 16 | CONF_OVERRIDE="${filename%.*}" 17 | 18 | # 检查文件名是否为"CONF"(不区分大小写) 19 | if [[ "${CONF_OVERRIDE,,}" == "conf" ]]; then 20 | echo "Error: Filename 'conf' is not allowed" 21 | exit 1 22 | fi 23 | 24 | # 如果用户没有设置 CONF,使用目录中的文件名 25 | if [ -z "$CONF" ]; then 26 | CONF="$CONF_OVERRIDE" 27 | fi 28 | 29 | # 根据命令参数执行操作 30 | case "$1" in 31 | clean) 32 | # 清理操作 33 | sudo systemctl stop "$CONF".service 2>/dev/null 34 | sudo systemctl disable "$CONF".service 2>/dev/null 35 | sudo rm -f /etc/conf.d/"$CONF".conf 36 | sudo rm -f /usr/lib/systemd/system/"$CONF".service 37 | ;; 38 | *) 39 | # 默认操作(安装服务) 40 | sudo mkdir -p /etc/conf.d 41 | sudo rm -f /etc/conf.d/"$CONF".conf 42 | sudo cp ./env/env /etc/conf.d/"$CONF".conf 43 | 44 | # 使用 ./system/ 中的第一个文件 45 | sudo cp "${system_files[0]}" /usr/lib/systemd/system/"$CONF".service 46 | { 47 | echo "EnvironmentFile=/etc/conf.d/$CONF.conf" 48 | echo 49 | echo "[Install]" 50 | echo "WantedBy=multi-user.target" 51 | } | sudo tee -a /usr/lib/systemd/system/"$CONF".service > /dev/null 52 | 53 | sudo systemctl daemon-reload 54 | sudo systemctl enable "$CONF".service 55 | sudo systemctl start "$CONF".service 56 | ;; 57 | esac -------------------------------------------------------------------------------- /linux-screen-tool/screen-tool.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # 工具名称和版本 4 | TOOL_NAME="screen-tool.sh" 5 | VERSION="1.0" 6 | 7 | # 显示帮助信息 8 | show_help() { 9 | cat << EOF 10 | ${TOOL_NAME} - 封装 screen 命令的实用工具 11 | 版本: ${VERSION} 12 | 13 | 用法: 14 | $TOOL_NAME write 向指定终端写入命令(不存在则创建) 15 | $TOOL_NAME read 读取终端输出 16 | $TOOL_NAME del 关闭终端 17 | $TOOL_NAME ls 列出所有终端 18 | $TOOL_NAME [-h|--help] 显示此帮助信息 19 | 20 | 示例: 21 | $TOOL_NAME write myterm "ls -l" 22 | $TOOL_NAME read myterm 23 | $TOOL_NAME del myterm 24 | EOF 25 | } 26 | 27 | # 检查会话是否存在 28 | session_exists() { 29 | screen -ls | grep -q "[0-9]\.$1\s" 30 | } 31 | 32 | # 创建新会话 33 | create_session() { 34 | screen -dmS "$1" /bin/bash -c "echo 'Session initialized'; exec /bin/bash" 35 | } 36 | 37 | # 写入命令到终端 38 | write_command() { 39 | local name="$1" 40 | local command="$2" 41 | 42 | # 检查会话是否存在,不存在则创建 43 | if ! session_exists "$name"; then 44 | echo "创建新会话: $name" 45 | create_session "$name" 46 | sleep 0.1 # 等待会话初始化 47 | fi 48 | 49 | # 发送命令并执行(追加换行符模拟回车) 50 | screen -S "$name" -X stuff "$command"$'\n' 51 | } 52 | 53 | # 读取终端输出 54 | read_output() { 55 | local name="$1" 56 | local tmpfile 57 | 58 | # 检查会话是否存在 59 | if ! session_exists "$name"; then 60 | echo "错误: 会话 '$name' 不存在" >&2 61 | exit 1 62 | fi 63 | 64 | # 创建临时文件存放输出 65 | tmpfile=$(mktemp) 66 | 67 | # 捕获当前屏幕内容 68 | screen -S "$name" -X hardcopy -h "$tmpfile" 69 | 70 | # 显示内容并清理 71 | cat "$tmpfile" 72 | rm -f "$tmpfile" 73 | } 74 | 75 | # 关闭终端会话 76 | delete_session() { 77 | local name="$1" 78 | 79 | if session_exists "$name"; then 80 | screen -S "$name" -X quit 81 | screen -wipe "$name" 82 | echo "已关闭会话: $name" 83 | else 84 | echo "错误: 会话 '$name' 不存在" >&2 85 | exit 0 86 | fi 87 | } 88 | 89 | # 列出所有会话 90 | list_sessions() { 91 | screen -ls 92 | } 93 | 94 | # 主程序逻辑 95 | case "$1" in 96 | write) 97 | if [ $# -lt 3 ]; then 98 | echo "错误: 缺少参数" >&2 99 | show_help 100 | exit 1 101 | fi 102 | write_command "$2" "${*:3}" 103 | ;; 104 | read) 105 | if [ $# -ne 2 ]; then 106 | echo "错误: 需要指定会话名称" >&2 107 | exit 1 108 | fi 109 | read_output "$2" 110 | ;; 111 | del) 112 | if [ $# -ne 2 ]; then 113 | echo "错误: 需要指定会话名称" >&2 114 | exit 1 115 | fi 116 | delete_session "$2" 117 | ;; 118 | ls) 119 | list_sessions 120 | ;; 121 | -h|--help|*) 122 | show_help 123 | exit 0 124 | ;; 125 | esac -------------------------------------------------------------------------------- /linux-user-manager/user-manager.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # 检查root权限 4 | check_root() { 5 | if [ "$(id -u)" -ne 0 ]; then 6 | echo "错误:此脚本需要root权限执行。请使用sudo运行!" 7 | exit 1 8 | fi 9 | } 10 | 11 | # 创建用户函数 12 | create_user() { 13 | read -p "请输入用户名: " username 14 | if id "$username" &>/dev/null; then 15 | echo "错误:用户 '$username' 已存在!" 16 | return 17 | fi 18 | 19 | read -s -p "请输入密码: " password 20 | echo 21 | read -s -p "确认密码: " password_confirm 22 | echo 23 | 24 | if [ "$password" != "$password_confirm" ]; then 25 | echo "错误:两次输入的密码不匹配!" 26 | return 27 | fi 28 | 29 | # 创建用户 30 | useradd -m -s /bin/bash "$username" &>/dev/null 31 | if [ $? -ne 0 ]; then 32 | echo "错误:创建用户失败!" 33 | return 34 | fi 35 | 36 | # 设置密码 37 | echo "$username:$password" | chpasswd 38 | echo "用户 '$username' 创建成功!" 39 | } 40 | 41 | # 创建管理员用户 42 | create_admin() { 43 | create_user 44 | if ! id "$username" &>/dev/null; then return; fi 45 | 46 | # 添加到sudo组(兼容不同发行版) 47 | if grep -q '^sudo:' /etc/group; then 48 | usermod -aG sudo "$username" 49 | elif grep -q '^wheel:' /etc/group; then 50 | usermod -aG wheel "$username" 51 | else 52 | echo "警告:未找到sudo或wheel组,已创建为普通用户。" 53 | return 54 | fi 55 | 56 | echo "管理员用户 '$username' 创建成功!" 57 | } 58 | 59 | # 修改密码 60 | change_password() { 61 | read -p "请输入用户名: " username 62 | if ! id "$username" &>/dev/null; then 63 | echo "错误:用户 '$username' 不存在!" 64 | return 65 | fi 66 | 67 | read -s -p "请输入新密码: " password 68 | echo 69 | read -s -p "确认新密码: " password_confirm 70 | echo 71 | 72 | if [ "$password" != "$password_confirm" ]; then 73 | echo "错误:两次输入的密码不匹配!" 74 | return 75 | fi 76 | 77 | echo "$username:$password" | chpasswd 78 | echo "用户 '$username' 的密码已更新!" 79 | } 80 | 81 | # 列举所有普通用户 82 | list_users() { 83 | echo "系统用户列表 (UID ≥ 1000):" 84 | echo "-------------------------" 85 | awk -F: '$3 >= 1000 && $3 < 60000 {print "用户名:", $1, " UID:", $3}' /etc/passwd 86 | } 87 | 88 | # 删除用户 89 | delete_user() { 90 | read -p "请输入要删除的用户名: " username 91 | if ! id "$username" &>/dev/null; then 92 | echo "错误:用户 '$username' 不存在!" 93 | return 94 | fi 95 | 96 | read -p "是否删除用户主目录?(y/n): " del_home 97 | if [ "$del_home" = "y" ]; then 98 | userdel -r "$username" 99 | else 100 | userdel "$username" 101 | fi 102 | 103 | # 检查删除结果 104 | if [ $? -eq 0 ]; then 105 | echo "用户 '$username' 已成功删除!" 106 | else 107 | echo "错误:删除用户失败!" 108 | fi 109 | } 110 | 111 | # 主菜单 112 | main_menu() { 113 | clear 114 | echo "=======================================" 115 | echo " Linux 用户管理系统" 116 | echo "=======================================" 117 | echo " 1. 创建普通用户" 118 | echo " 2. 创建管理员用户" 119 | echo " 3. 修改用户密码" 120 | echo " 4. 列出所有用户" 121 | echo " 5. 删除用户" 122 | echo " 6. 退出" 123 | echo "=======================================" 124 | } 125 | 126 | # 主循环 127 | check_root 128 | while true; do 129 | main_menu 130 | read -p "请选择操作 [1-6]: " choice 131 | 132 | case $choice in 133 | 1) create_user ;; 134 | 2) create_admin ;; 135 | 3) change_password ;; 136 | 4) list_users ;; 137 | 5) delete_user ;; 138 | 6) echo "感谢使用!"; exit 0 ;; 139 | *) echo "无效选择,请重新输入!" ;; 140 | esac 141 | 142 | read -p "按Enter键继续..." 143 | done -------------------------------------------------------------------------------- /linux-terminal-clipboard/terminal-clipboard.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # 检查是否提供了name参数 4 | if [ $# -eq 0 ]; then 5 | echo "Usage: $0 " 6 | exit 1 7 | fi 8 | 9 | NAME=$1 10 | CHAT_DIR="/tmp/terminal_chat_$NAME" 11 | LOG_FILE="${CHAT_DIR}/chat.log" 12 | LOCK_FILE="${CHAT_DIR}/lock" 13 | MSG_COUNTER_FILE="${CHAT_DIR}/counter" 14 | 15 | # 创建聊天目录 16 | mkdir -p "$CHAT_DIR" 17 | chmod 777 "$CHAT_DIR" 2>/dev/null || true 18 | 19 | # 初始化消息计数器 20 | if [ ! -f "$MSG_COUNTER_FILE" ]; then 21 | echo "0" > "$MSG_COUNTER_FILE" 22 | fi 23 | 24 | # 清理函数 25 | cleanup() { 26 | # 释放锁 27 | rm -f "$LOCK_FILE.$$" 28 | exit 0 29 | } 30 | 31 | # 设置信号处理 32 | trap cleanup INT TERM EXIT 33 | 34 | # 获取锁函数 35 | acquire_lock() { 36 | local max_attempts=10 37 | local attempt=0 38 | 39 | while [ $attempt -lt $max_attempts ]; do 40 | if ln -s $$ "$LOCK_FILE.$$" 2>/dev/null; then 41 | return 0 42 | fi 43 | sleep 0.1 44 | attempt=$((attempt + 1)) 45 | done 46 | return 1 47 | } 48 | 49 | # 释放锁函数 50 | release_lock() { 51 | rm -f "$LOCK_FILE.$$" 2>/dev/null 52 | } 53 | 54 | # 函数:发送消息 55 | send_message() { 56 | local message="$1" 57 | 58 | # 获取锁 59 | if acquire_lock; then 60 | # 获取并递增消息计数器 61 | local counter=$(cat "$MSG_COUNTER_FILE") 62 | echo $((counter + 1)) > "$MSG_COUNTER_FILE" 63 | 64 | # 使用base64编码消息内容,保留所有格式(包括空消息) 65 | local encoded_message=$(echo -n "$message" | base64 -w 0) 66 | 67 | # 写入编码后的消息到日志文件 68 | echo "$counter:$$:$encoded_message" >> "$LOG_FILE" 69 | 70 | # 释放锁 71 | release_lock 72 | fi 73 | } 74 | 75 | # 函数:获取消息计数器值 76 | get_message_counter() { 77 | cat "$MSG_COUNTER_FILE" 2>/dev/null || echo "0" 78 | } 79 | 80 | # 函数:处理新消息 81 | process_new_messages() { 82 | local current_counter=$1 83 | local last_counter=$2 84 | 85 | # 计算有多少条新消息 86 | local num_new_messages=$((current_counter - last_counter)) 87 | 88 | # 读取新消息 89 | local new_messages=$(tail -n "$num_new_messages" "$LOG_FILE" 2>/dev/null) 90 | 91 | # 处理每条新消息 92 | while IFS= read -r line; do 93 | if [ -n "$line" ]; then 94 | # 提取编码的消息内容和发送者终端ID 95 | local encoded_message=$(echo "$line" | cut -d: -f3-) 96 | local sender_pid=$(echo "$line" | cut -d: -f2) 97 | 98 | # 解码消息内容 99 | local msg_content=$(echo "$encoded_message" | base64 -d) 100 | 101 | # 只显示其他终端发送的消息(包括空消息) 102 | if [ "$sender_pid" -ne "$$" ]; then 103 | echo "$msg_content" 104 | fi 105 | fi 106 | done <<< "$new_messages" 107 | } 108 | 109 | # 后台进程:监听新消息 110 | { 111 | # 获取当前消息计数器值 112 | last_counter=$(get_message_counter) 113 | 114 | # 父进程PID 115 | PARENT_PID=$$ 116 | 117 | # 监听循环 118 | while true; do 119 | # 检查父进程是否还在运行 120 | if ! kill -0 $PARENT_PID 2>/dev/null; then 121 | exit 0 122 | fi 123 | 124 | # 获取锁 125 | if acquire_lock; then 126 | # 检查是否有新消息 127 | current_counter=$(get_message_counter) 128 | 129 | if [ "$current_counter" -gt "$last_counter" ]; then 130 | # 处理新消息 131 | process_new_messages "$current_counter" "$last_counter" 132 | 133 | # 更新最后计数器 134 | last_counter="$current_counter" 135 | fi 136 | 137 | # 释放锁 138 | release_lock 139 | fi 140 | 141 | # 短暂休眠以减少CPU使用 142 | sleep 0.5 143 | done 144 | } & 145 | 146 | # 主循环 - 读取用户输入并发送 147 | while true; do 148 | IFS= read -r message 149 | if [ "$message" = "exit" ]; then 150 | break 151 | fi 152 | # 发送所有输入,包括空输入 153 | # 发送消息到其他终端(包括空消息) 154 | send_message "$message" 155 | done 156 | 157 | cleanup -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # se-script 2 | 分享一些个人编写(AI编写)或改良的脚本 3 | 4 | ## 用户管理 5 | [脚本](./linux-user-manager/user-manager.sh) 6 | 7 | - 添加好可执行权限后直接运行即可 8 | - 需要Root权限 9 | 10 | ### cui菜单如下 11 | ``` 12 | "=======================================" 13 | " Linux 用户管理系统" 14 | "=======================================" 15 | " 1. 创建普通用户" 16 | " 2. 创建管理员用户" 17 | " 3. 修改用户密码" 18 | " 4. 列出所有用户" 19 | " 5. 删除用户" 20 | " 6. 退出" 21 | =======================================" 22 | ``` 23 | 24 | ## 防火墙 25 | [脚本](./linux-firewall/firewall-cui.sh) 26 | 27 | 通过修改iptables input链规则来放行传入端口与网段 28 | 29 | ### 警告 30 | 一旦执行该脚本就会立即清空iptables input链规则(不会操作output链,forward链),请确保无其他程序依赖iptables input链,以免发生网络异常 31 | 32 | 可执行`sudo iptables -S INPUT`查看iptables input链当前情况 33 | 34 | ### 原理 35 | 1. 启动脚本后会将iptables input链清空 36 | 2. 将input设置为drop, 放行icmp, 放行已建立的连接 37 | 3. 创建/etc/iptables-manager文件夹,用于存放规则文件 38 | 4. 重新加载/etc/iptables-manager下的规则到iptables input链 39 | 5. 启动cui 菜单界面 40 | 6. 保存新的规则并添加systemctl服务开机自启动 41 | 7. 重新加载规则到iptables input链 42 | 43 | ### CUI 菜单界面 44 | 45 | ``` 46 | "==================================================" 47 | " iptables 防火墙管理 (黑名单模式)" 48 | "==================================================" 49 | " 1. 放行TCP/UDP端口" 50 | " 2. 取消放行端口" 51 | " 3. 放行IP网段" 52 | " 4. 取消放行IP网段" 53 | " 5. 查看当前规则" 54 | " 6. 保存规则并持久化" 55 | " 0. 退出" 56 | "==================================================" 57 | ``` 58 | 59 | ### 运行方式 60 | - 添加好可执行权限后直接运行即可 61 | 62 | ## systemctl服务模版 63 | [脚本路径](./linux-systemctl-template) 64 | 65 | 快速创建systemctl自启动服务 66 | 67 | ### 使用方式 68 | 1. 复制`linux-systemctl-template`到随便一个地方并进入复制后的文件夹 69 | 2. 重命名`./system/conf`为`xxx`(`xxx`自己随便起一个名) 70 | 3. 打开`./system/xxx`, 根据里面的注释来修改(一般只需修改`Type`,`WorkingDirectory`,`ExecStart`就行) 71 | 4. (非必须) 如需要添加环境变量,则往`./env/env`里添加环境变量就行 72 | 5. 运行`./ser.sh`即可(会自动执行systemctl enable xxx; systemctl start xxx) 73 | 6. (非必须) 可通过`systemctl status xxx`查看服务状态 74 | 7. (非必须) 后续若要修改服务内容,先执行`./ser.sh clean`, 之后重复3-6即可 75 | 8. (非必须) 若需要删除该服务, 执行`./ser.sh clean` 76 | 77 | ### 原理 78 | 1. 获取`./system`文件夹中第一个文件名记为`xxx` 79 | 2. 执行 cp `./env/env` `/etc/conf.d/xxx` 80 | 3. 复制`./system/xxx`到`/etc/systemd/system/xxx.service` 81 | 4. 追加下述内容到`/etc/systemd/system/xxx.service` 82 | ``` 83 | "EnvironmentFile=/etc/conf.d/xxx.conf" 84 | "[Install]" 85 | "WantedBy=multi-user.target" 86 | ``` 87 | 5. 执行`systemctl enable xxx` 与 `systemctl start xxx` 88 | 89 | 6. 执行`./ser.sh clean`时,会执行下列命令 90 | - `systemctl disable xxx` 91 | - `systemctl stop xxx` 92 | - `rm /etc/systemd/system/xxx.service` 93 | - `rm /etc/conf.d/xxx.conf` 94 | 95 | ### 端口转发 96 | 97 | [脚本](./linux-socat-forward/port-forward.sh) 98 | 99 | 快速创建socat端口转发服务 100 | 需要安装好socat (注: `sudo apt install socat`) 101 | 102 | 运行方式: 103 | 104 | `./port-forward.sh <本地端口> <远程地址> <远程端口>` 105 | 106 | 示例: 107 | 108 | `./port-forward.sh 80 192.168.1.1 8080` 109 | - 80 -> 192.168.1.1:8080 110 | - 绑定`0.0.0.0:80`端口,将80端口的请求转发到`192.168.1.1:8080` 111 | 112 | ## 简化screen操作 113 | [脚本](./linux-screen-tool/screen-tool.sh) 114 | 115 | 用于简化screen操作 116 | 117 | ``` 118 | 用法: 119 | screen-tool.sh write 向名称为name的screen会话写入命令(不存在则创建)(自动添加换行符\n) 120 | screen-tool.sh read 读取名称为name的screen会话当前所有输出 121 | screen-tool.sh del 关闭名称为name的screen会话 122 | screen-tool.sh ls 列出所有screen会话 123 | screen-tool.sh [-h|--help] 显示此帮助信息 124 | 125 | 示例: 126 | screen-tool.sh write myterm "ls -l" 127 | screen-tool.sh read myterm 128 | screen-tool.sh del myterm 129 | ``` 130 | 131 | ### screen-tool.sh write 132 | 向指定的screen终端写入命令并自动添加换行符\n 若不存在该终端则会后台自动创建 133 | 134 | ### screen-tool.sh read 135 | 读取名称为name的screen终端当前所有输出 136 | 137 | ## 终端剪切板 138 | 139 | [脚本](./linux-terminal-clipboard/terminal-clipboard.sh) 140 | 141 | 类似于剪切板一样,在同一台Linux主机上,向a终端的输入内容会展示在a,b,c,d,e,f终端上。b终端的输入内容会展示在a,b,c,d,e,f终端上,以用于在不同的终端间共享信息。 142 | 143 | 这个是我在运行虚拟机时获得的灵感。在一个场景中,宿主机无法直接将大量数据直接通过CTRL+C/CTRL+V复制到虚拟机内部,虚拟机也同样无法将大片内容直接复制到宿主机里,手动一个一个敲上去又不太现实。正好宿主机可以通过ssh连接虚拟机。此时,宿主机通过ssh新建一个终端并运行该脚本,虚拟机也开一个桌面终端并运行该脚本。复制的内容输入到a终端,b终端就能立马显示,就解决这个问题。 144 | 145 | ### 特点 146 | - 支持多个终端绑定同一个name上。每个终端既可以展示内容,也可以直接当作输入源。 147 | - 数据会保存在/tmp/terminal_chat_\/chat.log上,可随时查看(注意,不会手动清除) 148 | 149 | ### 用法 150 | ``` 151 | ./terminal-clipboard.sh // 随便起一个名字就好。但注意只有相同name的终端才会展示相同的内容。 152 | 153 | //示例 154 | 155 | // a终端 156 | ./terminal-clipboard.sh test 157 | 158 | // b终端 159 | ./terminal-clipboard.sh test 160 | 161 | // c终端 162 | ./terminal-clipboard.sh test 163 | 164 | // 此时往a终端输入hello world, 回车 165 | 166 | a,b,c终端均会显示hello world 167 | ``` -------------------------------------------------------------------------------- /linux-firewall/firewall-cui.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # 配置目录 4 | CONFIG_DIR="/etc/iptables-manager" 5 | PORT_CONFIG="${CONFIG_DIR}/ports.conf" 6 | IPNET_CONFIG="${CONFIG_DIR}/ip_nets.conf" 7 | RULES_FILE="/etc/iptables/rules.v4" 8 | 9 | # 初始化配置 10 | init_config() { 11 | mkdir -p "$CONFIG_DIR" 12 | touch "$PORT_CONFIG" "$IPNET_CONFIG" 13 | 14 | # 创建端口配置文件结构 15 | if [ ! -s "$PORT_CONFIG" ]; then 16 | echo "# 格式: <协议> <端口>" > "$PORT_CONFIG" 17 | echo "# 示例: tcp 80" >> "$PORT_CONFIG" 18 | echo "# 示例: udp 53" >> "$PORT_CONFIG" 19 | fi 20 | } 21 | 22 | # 加载历史规则 23 | load_rules() { 24 | # 恢复端口规则 25 | while read -r line; do 26 | if [[ $line =~ ^(tcp|udp)[[:space:]]+[0-9]+$ ]]; then 27 | local proto=${line%% *} 28 | local port=${line##* } 29 | iptables -A INPUT -p "$proto" --dport "$port" -j ACCEPT 30 | fi 31 | done < <(grep -E '^(tcp|udp) [0-9]+' "$PORT_CONFIG") 32 | 33 | # 恢复IP网段规则 34 | while read -r cidr; do 35 | if [[ "$cidr" =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/[0-9]{1,2}$ ]]; then 36 | iptables -A INPUT -s "$cidr" -j ACCEPT 37 | fi 38 | done < "$IPNET_CONFIG" 39 | } 40 | 41 | # 初始化防火墙 42 | init_firewall() { 43 | # 清除所有规则 44 | iptables -F INPUT 45 | 46 | # 设置默认策略 47 | iptables -P INPUT DROP 48 | 49 | # 基本安全规则 50 | iptables -A INPUT -i lo -j ACCEPT 51 | iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT 52 | iptables -A INPUT -p icmp --icmp-type echo-request -j ACCEPT 53 | 54 | # 加载历史规则 55 | load_rules 56 | } 57 | 58 | # 放行端口 59 | allow_port() { 60 | while :; do 61 | read -p "协议 (tcp/udp): " proto 62 | [[ "$proto" =~ ^(tcp|udp)$ ]] && break 63 | echo "无效协议! 请输入 'tcp' 或 'udp'" 64 | done 65 | 66 | while :; do 67 | read -p "端口号 (1-65535): " port 68 | [[ "$port" =~ ^[0-9]{1,5}$ ]] && ((port >= 1 && port <= 65535)) && break 69 | echo "无效端口号! 请输入 1-65535 之间的值" 70 | done 71 | 72 | # 检查是否已存在 73 | if grep -q "^${proto} ${port}$" "$PORT_CONFIG"; then 74 | echo "⚠️ 规则已存在: ${proto}/${port}" 75 | return 76 | fi 77 | 78 | # 添加规则和配置 79 | iptables -A INPUT -p "$proto" --dport "$port" -j ACCEPT 80 | echo "${proto} ${port}" >> "$PORT_CONFIG" 81 | echo "✅ 已放行: ${proto}/${port}" 82 | } 83 | 84 | # 取消放行端口 85 | deny_port() { 86 | local count=1 87 | local entries=() 88 | 89 | echo "当前放行端口:" 90 | while read -r line; do 91 | if [[ "$line" =~ ^(tcp|udp)[[:space:]]+[0-9]+$ ]]; then 92 | printf "%-4s %-5s %s\n" "[$count]" "${line%% *}" "${line##* }" 93 | entries+=("$line") 94 | ((count++)) 95 | fi 96 | done < "$PORT_CONFIG" 97 | 98 | if [ ${#entries[@]} -eq 0 ]; then 99 | echo "没有可管理的端口规则" 100 | read -p "按Enter返回" 101 | return 102 | fi 103 | 104 | while :; do 105 | read -p "选择要取消的规则编号 [1-$((count-1))], 或 'a' 取消所有: " choice 106 | if [[ "$choice" = "a" ]]; then 107 | # 删除所有端口规则 108 | while read -r line; do 109 | if [[ "$line" =~ ^(tcp|udp)[[:space:]]+[0-9]+$ ]]; then 110 | local proto=${line%% *} 111 | local port=${line##* } 112 | iptables -D INPUT -p "$proto" --dport "$port" -j ACCEPT 113 | fi 114 | done < "$PORT_CONFIG" 115 | 116 | # 清空配置文件 117 | grep -vE '^(tcp|udp) [0-9]+' "$PORT_CONFIG" > "${PORT_CONFIG}.tmp" 118 | mv "${PORT_CONFIG}.tmp" "$PORT_CONFIG" 119 | 120 | echo "✅ 所有端口规则已取消" 121 | break 122 | elif [[ "$choice" =~ ^[0-9]+$ ]] && ((choice >= 1 && choice <= ${#entries[@]})); then 123 | local entry="${entries[$((choice-1))]}" 124 | local proto=${entry%% *} 125 | local port=${entry##* } 126 | 127 | # 从iptables删除 128 | iptables -D INPUT -p "$proto" --dport "$port" -j ACCEPT 129 | 130 | # 从配置文件中删除 131 | sed -i "/^${proto} ${port}$/d" "$PORT_CONFIG" 132 | 133 | echo "✅ 已取消: ${proto}/${port}" 134 | break 135 | else 136 | echo "无效选择!" 137 | fi 138 | done 139 | } 140 | 141 | # 放行IP网段 142 | allow_ipnet() { 143 | while :; do 144 | read -p "输入IP网段 (CIDR格式, 如 192.168.1.0/24): " cidr 145 | if [[ "$cidr" =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/[0-9]{1,2}$ ]]; then 146 | # 检查是否已存在 147 | if grep -q "^${cidr}$" "$IPNET_CONFIG"; then 148 | echo "⚠️ 规则已存在: ${cidr}" 149 | return 150 | fi 151 | 152 | # 添加规则和配置 153 | iptables -A INPUT -s "$cidr" -j ACCEPT 154 | echo "$cidr" >> "$IPNET_CONFIG" 155 | echo "✅ 已放行网段: ${cidr}" 156 | break 157 | else 158 | echo "❌ 无效CIDR格式! 正确示例: 192.168.1.0/24" 159 | fi 160 | done 161 | } 162 | 163 | # 取消放行IP网段 164 | deny_ipnet() { 165 | local count=1 166 | local entries=() 167 | 168 | echo "当前放行网段:" 169 | while read -r cidr; do 170 | if [[ "$cidr" =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/[0-9]{1,2}$ ]]; then 171 | printf "%-4s %s\n" "[$count]" "$cidr" 172 | entries+=("$cidr") 173 | ((count++)) 174 | fi 175 | done < "$IPNET_CONFIG" 176 | 177 | if [ ${#entries[@]} -eq 0 ]; then 178 | echo "没有可管理的网段规则" 179 | read -p "按Enter返回" 180 | return 181 | fi 182 | 183 | while :; do 184 | read -p "选择要取消的规则编号 [1-$((count-1))], 或 'a' 取消所有: " choice 185 | if [[ "$choice" = "a" ]]; then 186 | # 删除所有IP网段规则 187 | while read -r cidr; do 188 | if [[ "$cidr" =~ ^[0-9]+\.[0--9]+\.[0-9]+\.[0-9]+/[0-9]{1,2}$ ]]; then 189 | iptables -D INPUT -s "$cidr" -j ACCEPT 190 | fi 191 | done < "$IPNET_CONFIG" 192 | 193 | # 清空配置文件 194 | : > "$IPNET_CONFIG" 195 | 196 | echo "✅ 所有网段规则已取消" 197 | break 198 | elif [[ "$choice" =~ ^[0-9]+$ ]] && ((choice >= 1 && choice <= ${#entries[@]})); then 199 | local cidr="${entries[$((choice-1))]}" 200 | 201 | # 从iptables删除 202 | iptables -D INPUT -s "$cidr" -j ACCEPT 203 | 204 | # 从配置文件中删除 205 | sed -i "\|^${cidr}$|d" "$IPNET_CONFIG" 206 | 207 | echo "✅ 已取消网段: ${cidr}" 208 | break 209 | else 210 | echo "无效选择!" 211 | fi 212 | done 213 | } 214 | 215 | # 保存规则 216 | save_rules() { 217 | echo "💾 正在保存规则..." 218 | mkdir -p "$(dirname "$RULES_FILE")" 219 | iptables-save > "$RULES_FILE" 220 | 221 | # 设置系统启动加载 222 | if [[ -f "/etc/init.d/iptables" || -d "/etc/systemd/system" ]]; then 223 | echo " 正在配置开机自动加载规则..." 224 | # Systemd系统 225 | if systemctl is-enabled iptables 2>/dev/null | grep -q enabled; then 226 | echo " 使用系统iptables服务" 227 | [ -d "/etc/iptables" ] || mkdir -p /etc/iptables 228 | cp "$RULES_FILE" "/etc/iptables/rules.v4" 229 | systemctl restart iptables 230 | else 231 | # 创建自定义服务 232 | cat << EOF > /etc/systemd/system/iptables-manager.service 233 | [Unit] 234 | Description=IPTables Persistent Service 235 | After=network.target 236 | 237 | [Service] 238 | Type=oneshot 239 | ExecStart=/sbin/iptables-restore -n "$RULES_FILE" 240 | RemainAfterExit=yes 241 | 242 | [Install] 243 | WantedBy=multi-user.target 244 | EOF 245 | systemctl daemon-reload 246 | systemctl enable --now iptables-manager 247 | fi 248 | elif [ -x "/etc/init.d/iptables" ]; then 249 | # SysVinit系统 250 | echo " 使用SysVinit iptables服务" 251 | /etc/init.d/iptables save 252 | /etc/init.d/iptables restart 253 | fi 254 | 255 | echo "✅ 规则已保存并将在系统重启后自动加载" 256 | read -p "按Enter返回菜单" 257 | } 258 | 259 | # 显示当前规则 260 | show_current_rules() { 261 | clear 262 | echo "==================================================" 263 | echo " 当前防火墙规则" 264 | echo "==================================================" 265 | 266 | echo -e "\n------ 默认策略 -----" 267 | iptables -L | grep -E "Chain (INPUT|FORWARD|OUTPUT)" 268 | 269 | echo -e "\n------ 端口放行规则 -----" 270 | local count=0 271 | while read -r line; do 272 | if [[ "$line" =~ ^(tcp|udp)[[:space:]]+[0-9]+$ ]]; then 273 | printf "%-5s %-4s %s\n" "PORT" "${line%% *}" "${line##* }" 274 | ((count++)) 275 | fi 276 | done < "$PORT_CONFIG" 277 | ((count == 0)) && echo "无" 278 | 279 | echo -e "\n------ IP网段放行规则 -----" 280 | count=0 281 | while read -r cidr; do 282 | if [[ "$cidr" =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/[0-9]{1,2}$ ]]; then 283 | echo "NET $cidr" 284 | ((count++)) 285 | fi 286 | done < "$IPNET_CONFIG" 287 | ((count == 0)) && echo "无" 288 | 289 | echo -e "\n------ 活动连接统计 -----" 290 | iptables -L -v | grep -E "(ACCEPT|DROP)" 291 | 292 | echo "==================================================" 293 | read -p "按Enter返回菜单" 294 | } 295 | 296 | # 主菜单 297 | main_menu() { 298 | while :; do 299 | clear 300 | echo "==================================================" 301 | echo " iptables 防火墙管理 (黑名单模式)" 302 | echo "==================================================" 303 | echo " 1. 放行TCP/UDP端口" 304 | echo " 2. 取消放行端口" 305 | echo " 3. 放行IP网段" 306 | echo " 4. 取消放行IP网段" 307 | echo " 5. 查看当前规则" 308 | echo " 6. 保存规则并持久化" 309 | echo " 0. 退出" 310 | echo "==================================================" 311 | 312 | # 显示简单状态 313 | local port_count=$(grep -cE '^(tcp|udp) [0-9]+' "$PORT_CONFIG") 314 | local net_count=$(grep -cE '^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/[0-9]{1,2}$' "$IPNET_CONFIG") 315 | printf " 状态: 放行端口:%-4d 放行网段:%-4d\n" "$port_count" "$net_count" 316 | echo "==================================================" 317 | 318 | 319 | read -p " 请输入选项 [0-6]: " choice 320 | case $choice in 321 | 1) allow_port ;; 322 | 2) deny_port ;; 323 | 3) allow_ipnet ;; 324 | 4) deny_ipnet ;; 325 | 5) show_current_rules ;; 326 | 6) save_rules ;; 327 | 0) 328 | read -p "是否保存当前规则更改? [y/N]: " save_choice 329 | if [[ "$save_choice" =~ ^[Yy]$ ]]; then 330 | save_rules 331 | fi 332 | exit 0 333 | ;; 334 | *) echo "无效选项!"; sleep 1 ;; 335 | esac 336 | done 337 | } 338 | 339 | # 启动 340 | if [ "$(id -u)" != "0" ]; then 341 | echo "❌ 必须使用 root 权限运行此脚本!" >&2 342 | exit 1 343 | fi 344 | 345 | echo "一旦执行该脚本就会立即清空iptables input链规则" 346 | echo "请确保无其他程序依赖iptables input链" 347 | echo "以免发生网络异常" 348 | echo "可执行 sudo iptables -S INPUT 查看iptables input链当前情况" 349 | 350 | while true; do 351 | read -p "是否继续? [y/Y]: " input # 提示用户输入 352 | case "$input" in 353 | [yY]) # 匹配 y 或 Y 354 | echo "继续执行..." 355 | break # 跳出循环继续执行后续代码 356 | ;; 357 | "") # 匹配空输入 358 | ;; 359 | *) # 匹配其他任何字符 360 | echo "输入错误,退出!" 361 | exit 1 # 立即退出脚本 362 | ;; 363 | esac 364 | done 365 | 366 | # 初始化配置和环境 367 | init_config 368 | init_firewall 369 | 370 | # 检查是否已有规则 371 | if ! iptables -L INPUT -n &> /dev/null; then 372 | echo -e "\n⚠️ 警告: 当前系统未安装 iptables" 373 | if command -v apt &> /dev/null; then 374 | read -p "是否安装 iptables? [Y/n]: " install_choice 375 | [[ "$install_choice" =~ ^[Nn]$ ]] || apt install -y iptables 376 | elif command -v yum &> /dev/null; then 377 | read -p "是否安装 iptables? [Y/n]: " install_choice 378 | [[ "$install_choice" =~ ^[Nn]$ ]] || yum install -y iptables iptables-services 379 | fi 380 | fi 381 | 382 | # 启动主菜单 383 | main_menu --------------------------------------------------------------------------------