小星的编程笔记

  • 腾讯云 &阿里云自动申请续费ssl证书

    腾讯云阿里云只要配置一次 API,以后证书就会全自动续期。

    假设你的环境:

    • 域名:aspu.top
    • DNS:腾讯云 DNSPod
    • Nginx 证书目录:/etc/nginx/ssl/aspu.top_nginx
    • 服务器:Linux
    • 使用 acme.sh

    第一步:安装 acme.sh

    curl https://get.acme.sh | sh
    source ~/.bashrc
    

    查看版本:

    acme.sh --version
    

    第二步:创建腾讯云 API 密钥

    登录腾讯云控制台:

    访问管理(CAM) → API 密钥管理

    创建:

    SecretId
    SecretKey
    

    例如:

    SecretId = AKIDxxxxxxxxxxxxxxxx
    
    SecretKey = xxxxxxxxxxxxxxxxx
    

    建议不要使用主账号,而是创建一个 CAM 子账号,只授予 DNS 相关权限(例如 DNSPod 管理权限),这样更安全。


    第三步:配置 API

    执行:

    
    # 1. 切换到 Let's Encrypt
    acme.sh --set-default-ca --server letsencrypt
    
    # 2. 设置腾讯云 API
    export Tencent_SecretId="你的SecretId"
    export Tencent_SecretKey="你的SecretKey"
    
    如果是阿里云
    export Ali_Key="xxxx"
    export Ali_Secret="xxxx"

    例如:

    export Tencent_SecretId="AKIDxxxxxxxxxxxxxxxx"
    export Tencent_SecretKey="xxxxxxxxxxxxxxxxxxxx"
    

    第一次申请成功后,acme.sh 会把这两个值保存到:

    ~/.acme.sh/account.conf
    

    以后不用再 export。


    第四步:申请证书

    如果申请:

    aspu.top
    www.aspu.top
    

    执行:

    腾讯云
    acme.sh --issue \
        --server letsencrypt \
        --dns dns_tencent \
        -d aspu.top \
        -d www.aspu.top \
        --keylength 2048 \
        --force
    
    如果是阿里云
    acme.sh --issue \
        --server letsencrypt \
        --dns dns_ali \
        -d aspu.top \
        -d www.aspu.top \
        --keylength 2048 \
        --force

    如果申请通配符:

    *.aspu.top
    

    执行:

    腾讯云
    acme.sh --issue \
        --server letsencrypt \
        --dns dns_tencent \
        -d aspu.top \
        -d '*.aspu.top' \
        --keylength 2048 \
        --force
    
    
    如果是阿里云
    
    acme.sh --issue \
        --server letsencrypt \
        --dns dns_ali \
        -d aspu.top \
        -d '*.aspu.top' \
        --keylength 2048 \
        --force

    acme.sh 会自动:

    调用腾讯云 API
            │
    新增 _acme-challenge TXT
            │
    等待解析
            │
    Let's Encrypt 验证
            │
    删除 TXT
            │
    签发证书
    

    整个过程无需登录腾讯云后台。


    第五步:安装到你的 nginx

    你的 nginx 已经使用:

    ssl_certificate /etc/nginx/ssl/aspu.top_nginx/aspu.top_bundle.crt;
    ssl_certificate_key /etc/nginx/ssl/aspu.top_nginx/aspu.top.key;
    

    因此执行:

    acme.sh --install-cert -d aspu.top \
      --key-file /etc/nginx/ssl/aspu.top_nginx/aspu.top.key \
      --fullchain-file /etc/nginx/ssl/aspu.top_nginx/aspu.top_bundle.crt \
      --reloadcmd "/usr/sbin/nginx -s reload"
    

    如果你的 nginx 是 systemd 管理的,则改成:

    --reloadcmd "systemctl reload nginx"
    
    
    验证 
    openssl pkey -in /ewomail/nginx/conf/ssl_cert/aspu.top_nginx/aspu.top.key -text -noout
    
    正常应该看到类似:
    
    Private-Key: (2048 bit)
    

    第六步:以后会发生什么?

    acme.sh 安装时已经创建了定时任务:

    crontab -l
    

    一般能看到:

    35 0 * * * "/root/.acme.sh"/acme.sh --cron --home "/root/.acme.sh" >/dev/null
    

    每天执行一次。

    流程如下:

    每天运行
        │
    检查证书
        │
    剩余约30天
        │
    自动申请新证书
        │
    覆盖:
    
    /ewomail/nginx/conf/ssl_cert/aspu.top_nginx/
    
        │
    执行
    
    /ewomail/nginx/sbin/nginx -s reload
    

    整个过程不需要人工参与。


    最后提醒一个关键点: dns_tencent 使用的是腾讯云 API(CAM 的 SecretId/SecretKey),不是 DNSPod 的 Token。如果你的域名是在腾讯云 DNS 控制台管理,使用上面的方式即可。若你的域名是在独立 DNSPod 平台管理,则需要使用对应的 dns_dp 插件和 DNSPod 的 API Token。

  • Linux 查看 Python 后台进程实际运行路径和文件路径

    在 Linux 服务器中,经常会使用:

    python3 app.py
    

    启动 Python 程序。

    但是运行一段时间后,通过:

    ps -ef | grep app.py
    

    查看进程时,可能只能看到:

    root     17322 23123  0 Mar24 pts/12   05:28:54 python3 app.py
    

    这里看不到:

    • 使用的是哪个 Python 解释器
    • app.py 文件实际在哪个目录

    这时候可以通过 /proc 查看进程真实信息。


    1. 查看 Python 解释器路径

    先获取进程 PID:

    PID = 17322
    

    执行:

    readlink -f /proc/17322/exe
    

    输出:

    /usr/local/python3.9.13/bin/python3.9
    

    说明这个程序实际使用的 Python:

    /usr/local/python3.9.13/bin/python3.9
    

    而不是系统默认的:

    /usr/bin/python3
    

    2. 查看 app.py 所在目录

    执行:

    readlink -f /proc/17322/cwd
    

    输出:

    /root/newapi/222/fastapi2
    

    这里表示程序启动时所在的工作目录。

    因为启动命令是:

    python3 app.py
    

    所以实际运行的文件就是:

    /root/newapi/222/fastapi2/app.py
    

    3. 一条命令查看完整信息

    以后遇到不知道路径的 Python 服务,可以执行:

    PID=17322
    
    echo "Python路径:"
    readlink -f /proc/$PID/exe
    
    echo "运行目录:"
    readlink -f /proc/$PID/cwd
    
    echo "启动命令:"
    cat /proc/$PID/cmdline | tr '\0' ' '
    

    输出类似:

    Python路径:
    /usr/local/python3.9.13/bin/python3.9
    
    运行目录:
    /root/newapi/222/fastapi2
    
    启动命令:
    python3 app.py
    

    最终可以确定:

    /usr/local/python3.9.13/bin/python3.9 /root/newapi/222/fastapi2/app.py
    

    4. 为什么 uvicorn 可以直接看到路径?

    例如:

    uvicorn main:app --host 0.0.0.0 --port 6010
    

    查看:

    ps -ef | grep uvicorn
    

    通常能看到:

    /usr/local/bin/python3 /usr/local/bin/uvicorn main:app
    

    原因是:

    uvicorn 本身是一个可执行入口文件。

    而:

    python3 app.py
    

    只是 Python 解释器加载脚本,Linux 进程参数只记录:

    python3 app.py
    

    不会自动展开成:

    /usr/local/python3.9.13/bin/python3.9 /root/newapi/222/fastapi2/app.py
    

    5. 生产环境建议

    不要直接:

    python3 app.py
    

    建议使用绝对路径:

    /usr/local/python3.9.13/bin/python3.9 \
    /root/newapi/222/fastapi2/app.py
    

    或者虚拟环境:

    /root/newapi/venv/bin/python \
    /root/newapi/222/fastapi2/app.py
    

    这样以后查看:

    ps -ef
    

    就能快速确认运行环境。


    总结

    需求命令
    查看 Python 路径readlink -f /proc/PID/exe
    查看程序目录readlink -f /proc/PID/cwd
    查看启动参数cat /proc/PID/cmdline | tr '\0' ' '

    Linux 中即使 ps 看不到完整路径,也可以通过 /proc/PID 精确找到 Python 程序真实运行位置。

  • Python 程序后台运行与日志自动管理教程

    本文介绍使用 nohup + tail + logrotate 实现简单稳定的 Python 服务日志管理方案。


    一、Python 程序后台运行

    普通执行:

    python3 app.py
    

    当关闭 SSH 连接后,程序会停止运行。

    可以使用 nohup 将程序放到后台运行:

    nohup python3 -u app.py > /root/logs/app.log 2>&1 &
    
    如果是uvicorn   不需要 -u 本来就是实时输出的
    nohup uvicorn main:app --host 0.0.0.0 --port 8000 > /root/logs/app.log 2>&1 &

    参数说明:

    参数作用
    nohup退出 SSH 后程序继续运行
    -uPython 无缓冲模式,日志实时写入
    > app.log保存程序输出日志
    2>&1错误日志一起写入
    &后台运行

    其中:

    -u
    

    表示 Python 使用 unbuffered(无缓冲)模式

    开启后:

    • print() 输出立即写入日志
    • tail -f 可以实时看到最新内容
    • 更适合长期运行的后台任务

    二、实时查看运行日志

    程序启动后,可以通过:

    tail -f /root/logs/app.log
    

    实时查看运行状态。

    例如:

    正在启动服务...
    连接数据库成功
    任务执行中...
    

    日志会不断刷新。

    退出查看:

    Ctrl + C
    

    三、配置日志自动清理

    如果程序长期运行:

    app.log
    

    会不断增大。

    当日志达到几个 GB 时,会占用大量磁盘空间。

    可以使用 Linux 自带的 logrotate 自动管理。

    创建配置文件:

    vim /etc/logrotate.d/app
    

    写入:

    /root/logs/*.log {
        daily
        rotate 7
        compress
        missingok
        copytruncate
        dateext
        dateformat -%Y-%m-%d
    }
    
    copytruncate 防止 Python 进程还占用旧文件句柄 写入新文件失败 不重启程序切割日志。
    每天一个文件最多7天

    四、logrotate 配置说明

    每天检查日志

    daily
    

    每天执行一次日志检查。


    限制日志大小

    size 100M
    

    当日志超过 100MB 时自动切割。


    保留历史日志

    rotate 7
    

    最多保留 7 个旧日志:

    app.log
    app.log.1.gz
    app.log.2.gz
    ...
    app.log.7.gz
    

    超过后自动删除。


    压缩旧日志

    compress
    

    旧日志自动压缩:

    app.log.1
    
    ↓
    
    app.log.1.gz
    

    减少磁盘占用。


    不重启程序切割日志

    copytruncate
    

    轮转日志时:

    • 复制旧日志
    • 清空当前日志文件

    程序无需停止或重启。

    适合:

    • Python 脚本
    • 爬虫程序
    • 后台任务
    • nohup 启动程序

    五、测试日志轮转

    查看配置是否正确:

    logrotate -d /etc/logrotate.d/app
    

    立即执行轮转:

    logrotate -f /etc/logrotate.d/app
    

    查看日志目录:

    ls -lh /root/logs/
    

    六、完整使用流程

    1. 启动 Python 程序

    nohup python3 -u app.py > /root/logs/app.log 2>&1 &
    

    2. 查看实时日志

    tail -f /root/logs/app.log
    

    3. 自动日志管理

    系统每天自动执行:

    app.log
          |
          | 超过100MB
          ↓
    app.log.1.gz
    app.log.2.gz
    ...
    app.log.7.gz
    

    自动保留最近 7 份日志,避免日志无限增长。

    七、如何一键重启

    kill 是 根据PID查询  pkill是根据 根据进程名/匹配规则搜索(所以最好先ps -ef|grep "xxx"  看一下是不是自己要的进程)
    
    pkill -f "python3 -u app.py"; nohup python3 -u app.py > /root/logs/app.log 2>&1 &
    
    
    pkill -f "uvicorn main:app"; nohup uvicorn main:app --host 0.0.0.0 --port 8000 > /root/logs/app.log 2>&1 &
    

    总结

    通过:

    • nohup 实现 Python 程序后台运行
    • python3 -u 保证日志实时输出
    • tail -f 实时查看运行状态
    • logrotate (log 肉泰特)自动切割和删除日志

    可以快速搭建一个简单可靠的 Python 服务运行环境,适合服务器脚本、爬虫、API 服务和定时任务等场景。

  • ubuntu设置系统时区

    新安装ubuntu系统可能不是东八区

    查看当前时区  timedatectl
    
    root@xxx:~# timedatectl
                   Local time: Sun 2026-07-19 15:16:02 CST
               Universal time: Sun 2026-07-19 07:16:02 UTC
                     RTC time: Sun 2026-07-19 07:16:02
                    Time zone: Asia/Shanghai (CST, +0800)
    System clock synchronized: yes
                  NTP service: active
              RTC in local TZ: no
    
    首先将硬件时钟设为标准的 UTC 模式(消除报错警告)
    sudo timedatectl set-local-rtc 0
    
    然后设置本地时区为东八区
    sudo timedatectl set-timezone Asia/Shanghai
    
    然后查看  
    timedatectl

  • 快速释放mysql表空间

    方案一(推荐★★★★★):新建表 + 导入最近1个月数据(最快释放空间)

    这是互联网公司最常用的方法。

    例如:

    创建一个和 table1 结构完全相同的新表 table1_new,但不复制任何数据。
    
    CREATE TABLE table1_new LIKE table1;
    

    导入最近一个月:

    INSERT INTO table1_new
    SELECT *
    FROM table1
    WHERE create_at >= NOW() - INTERVAL 1 MONTH;

    确认数据:

    SELECT COUNT(*) FROM table1;
    SELECT COUNT(*) FROM table1_new;

    然后

    RENAME TABLE
    table1 TO table1_old,
    table1_new TO table1;

    观察几天没问题:

    DROP TABLE table1_old;

    立即释放50GB左右空间。

    优点

    ✅ 不会产生大量undo

    ✅ 不会锁很久(只有rename瞬间)

    ✅ DROP TABLE秒完成

    ✅ 空间立即释放

    这是MySQL官方都推荐的大表清理方式。

  • nano编辑器

    nano 的设计哲学就是简单直观。它的核心优势在于,所有常用操作都像菜单一样显示在屏幕底部,几乎不需要学习成本。

    1. 核心特点

    • 开箱即用:打开、编辑、保存、退出,所见即所得。
    • 快捷键提示:底部两行会显示最常用命令的快捷键,^ 代表 Ctrl 键,M- 代表 Meta 键(通常是 Alt 或 Esc)。
    • 轻量快速:占用资源极少,几乎在所有 Linux 系统中都预装。
    • 无模式编辑:没有 Vim 那种“插入/命令模式”的切换概念,敲下字母键就是输入。

    2. 常用操作速查

    这里的 ^ 代表 Ctrl 键。

    • 打开文件nano 文件名 或 nano -l 文件名 (-l 显示行号)
    • 保存Ctrl + O,然后按 Enter 确认。
    • 退出Ctrl + X,若有未保存修改会提示。
    • 剪切一整行Ctrl + K
    • 粘贴Ctrl + U
    • 搜索Ctrl + W,输入关键词后回车,重复按会跳到下一处。
    • 撤销/重做Alt + U 撤销, Alt + E 重做。
    • 跳转到指定行Ctrl + _ 或 Ctrl + /,然后输入行号。
    • 显示帮助Ctrl + G

    3. 进阶技巧

    • 只读模式查看文件nano -v 文件名
    • 将光标定位到特定行/列nano +行号,列号 文件名,比如 nano +10,5 test.txt
    • 平滑滚动:加上 -S 参数。
    • 设置选项永久生效:编辑 ~/.nanorc 文件,可配置语法高亮、自动缩进、鼠标支持等。例如加入 set mouse 就能启用鼠标点击定位。
  • tee命令

    tee 是一个非常实用的 Linux 命令,它的核心作用就像是一个 T 型三通管,可以把数据流同时分流到文件和屏幕上

    一、基本原理:为何叫 T 型管?

    tee 的名字来源于管道行业中的 T 型三通接头。数据从一端流入,从另外两端原样流出。

    在 Linux 中,这表现为:
    从标准输入(stdin)读取数据,然后同时写入到标准输出(stdout,通常是屏幕)和指定的一个或多个文件。

    它的基本语法是:

    command | tee [选项] 文件1 [文件2...]
    
    
    
    
    

    二、核心用途与场景

    1. 最经典的场景:记录日志并实时查看

    运行一个长时间脚本时,你既想在屏幕上看到实时输出,又想将输出保存到日志文件中以供事后排查。

    ./install_script.sh | tee install.log
    
    
    
    
    

    这样,输出既会显示在终端,又会完整地保存到 install.log 里。

    2. 追加写入,而非覆盖

    默认情况下,tee 会覆盖文件内容。如果只想追加到文件末尾,使用 -a (append) 选项。

    ls -l | tee -a file_list.txt
    
    
    
    
    

    3. 解决权限问题的利器

    这是 tee 一个非常巧妙的用法。当你使用 sudo echo "内容" > /etc/profile 时,会提示权限不足,因为重定向符号 > 是由当前的 shell 执行的,而非 sudo,sudo 只会提升 echo 的权限,而 >> 或 > 依然以普通用户的权限去写入 /etc/profile,最终会提示“权限不够 (Permission denied)”。
    利用 tee 就能完美解决:

    echo "new config line" | sudo tee /etc/some_config.conf > /dev/null
    
    # 如果不想看到屏幕输出,可以重定向到 /dev/null
    
    
    
    
    

    4. 分发数据到多个文件

    可以将一份数据同时写入多个文件,这在需要备份或处理相同数据时很高效。

    echo "important data" | tee file1.txt file2.txt backup/file3.txt
    
    
    
    
    

    5. 在管道中间调试

    在一个非常长的命令管道中,你可以插入 tee 来截获中间数据,查看管道这一步的输出是否符合预期,而不中断整个流程。

    cat access.log | grep "ERROR" | tee /tmp/error_grep.log | cut -d' ' -f1 | sort | uniq -c

    这行命令在 grep 之后,将结果一边保存到临时文件 /tmp/error_grep.log 供你检查,一边继续传递给后面的 cut 命令。

    6. 写入 /dev/null 来模拟纯传递

    如果你只想把输出写入文件,完全不想在屏幕上显示,可以把标准输出重定向到 /dev/null。这等价于普通的 > 重定向,但结合 sudo 或其它场景时会用到。

    echo "secret" | tee private.key > /dev/null
    
    
    
    
    

    三、高级用法:活用文件描述符

    tee 不仅能处理标准输出,还能借助进程替换 >(...) 把数据喂给其他命令。

    例如,你想一边看原始输出,一边实时统计行数并压缩存档:

    # 将 data 命令的输出,一边在屏幕显示,一边传给 wc -l 统计行数,一边压缩保存
    data_command | tee >(wc -l > count.txt) | gzip > data.gz
    
    
    
    
    

    再比如,同时保存原始日志和过滤后的错误日志:

    cat program.log | tee raw_output.log | grep "ERROR" > errors.log
    # 但请注意,这里管道后面的 grep 收到的数据依然是 tee 转发给标准输出的完整数据。
    # 更精确的用法是用进程替换:
    cat program.log | tee raw_output.log >(grep "ERROR" > errors.log) > /dev/null
    
    
    
    
    

    四、常用选项总结

    • -a, --append:追加到文件,而不是覆盖。
    • -i, --ignore-interrupts:忽略中断信号(Ctrl+C),这在脚本中想让 tee 优雅退出时有用。
    • -p:诊断写入到管道时的错误,非标准输出。
    • --output-error[=模式]:当写入到任何输出发生错误时的行为,模式可以是 warnwarn-nopipeexitexit-nopipe,用于更精细地控制错误处理。

    五、与其他命令的对比

    • 重定向 >:只能将输出写入文件,屏幕上无显示。
    • tee:写入文件的同时输出到屏幕(或传递给下一个命令),这是它不可替代的核心价值。
    • script 命令:可以记录整个终端会话的全部输入和输出,功能更重,适合“录屏”,而 tee 更轻量,适合处理单个命令流。

    总而言之,tee 是一个在命令行中构建数据流处理管线时不可或缺的“分流器”,掌握它能让你更灵活地监控、记录和调试命令。

  • Linux文件追加文本

    在 Linux 中,向文件末尾添加信息最常用的命令是 echo 配合重定向符 >>

    1. 最基础、最常用的命令

    使用 >> 符号,它会将内容追加到文件末尾,而不会覆盖原有内容(注意:千万不要用 >,那是覆盖文件)。

    echo "你要添加的内容" >> 文件名.txt
    echo 'export MYSQL_HOST="127.0.0.1"' >> /etc/profile

    2. 添加多行内容(使用 Here Document)

    如果您需要一次性在文件末尾追加多行内容,使用 <<EOF 语法非常方便,不需要写多个 echo

    cat <<EOF >> 文件名.txt
    第一行内容
    第二行内容
    export MYSQL_HOST="127.0.0.1"
    export MYSQL_PORT="3306"
    EOF

    (注:这里的 EOF 只是一个结束标记,您可以换成 ENDSTOP 等任意字符串,只要首尾对应即可。)


    3. 追加文件内容到另一个文件
    如果您想把 a.txt 的内容追加到 b.txt 的末尾:

    cat a.txt >> b.txt


    4. 追加内容但不换行
    默认情况下,echo 会在末尾自动加一个换行符。如果您希望追加的内容和原文件最后一行连在一起,可以使用 -n 参数:

    echo -n "不换行追加的内容" >> 文件名.txt


  • 终端常用快捷键

    删除类
    --------------------------------
    ✔ Ctrl + W
    
    ? 删除光标前一个单词
    
    ✔ Ctrl + U
    
    ? 删除光标到行首
    
    ✔ Ctrl + K
    
    ? 删除光标到行尾
    
    ✔ Ctrl + L
    
    ? 清屏
    
    --------------------------------
    移动类
    
    Home  移动到行首
    
    End   移动到行尾
    
    ✔ Alt + B
    
    ? 向左跳一个单词
    
    ✔ Alt + F
    
    ? 向右跳一个单词
    --------------------------------
    其他类
    
    ✔ Ctrl + C
    
    ? 强制终止当前命令
    
    ✔ Tab
    
    ? 自动补全(最重要)
    
    ✔ 双击 Tab
    
    ? 显示所有可选项

    windows powershell常用快捷键

    Ctrl+Home   删除到行首
    Ctrl+End    删除到行尾
    Home        移动到行首
    End         移动到行尾
    
    ✔ Ctrl + Backspace
    
    ? 删除前一个单词(⭐相当于 Linux Ctrl+W)
    
    ✔ Ctrl + Delete
    
    
    ? 删除后一个单词
    
    ✔ Ctrl + Shift + T
    
    ? 新建标签页
    
    ✔ Ctrl + Shift + W
    
    ? 关闭标签页
    
    ✔ Ctrl + Shift + C
    
    ? 复制
    
    ✔ Ctrl + Shift + V
    
    ? 粘贴
    
    

  • scp传输文件

    一、传到服务器 B(账号+密码登录)

    服务器信息

    • IP:11.22.33.44
    • 用户:root
    • 密码:12345678
    • 端口:1234
    • 本地文件:a.txt
    • 目标路径:/root/test/

    ❗标准 scp 命令

    scp  -P 1234 a.txt root@11.22.33.44:/root/test/

    ⚠️关键点(很重要)

    scp 不能直接在命令里写密码

    ? 服务器返回需要输入密码:

    root@11.22.33.44's password:

    然后手动输入:

    12345678

    二、传到服务器 C(使用密钥 s.key)

    服务器信息

    • IP: 55.66.77.88
    • 用户:root
    • 密钥:s.key
    • 端口:1234
    • 文件:a.txt
    • 目标路径:/root/test/

    ❗标准 scp(指定私钥)

    scp -P 1234 -i s.key a.txt root@55.66.77.88:/root/test

    ?如果 key 需要权限修复(常见问题)

    chmod 600 s.key

    ?更完整写法(推荐)

    scp -P 1234 -i s.key -o StrictHostKeyChecking=no a.txt root@55.66.77.88:/root/test/

    限制速率目标:5 MB/s

    换算:

    5 MB/s
    = 5 × 8 = 40 Mbps
    = 40000 Kbit/s

    普通密码登录版本

    scp -l 40000 a.txt root@11.22.33.44:/root/test

    2️⃣ 指定密钥版本

    scp -i s.key -l 40000 a.txt root@55.66.77.88:/root/test

    ⭐ rsync 限速(推荐)

    限速单位:KB/s(更直观)

    5 MB/s = 5120 KB/s
    rsync -avz --bwlimit=5120 a.txt root@11.22.33.44:/root/test

    ⭐ rsync + key

    rsync -avz -e "ssh -i s.key" --bwlimit=5120 a.txt root@55.66.77.88:/root/test