ubuntu python虚拟环境venv搭配systemd服务实战(禁用缓存下载--no-cache-dir)

news2024/12/29 16:32:06

文章目录

    • 参考文章
    • 目录结构
    • 步骤
      • 安装venv
      • 查看python版本
      • 创建虚拟环境
      • 激活虚拟环境
      • 运行我们程序看缺少哪些依赖库,依次安装它们
      • 接下来我们配置python程序启动脚本,脚本中启动python程序前需先激活虚拟环境
      • 配置.service文件
      • 然后执行部署脚本,成功了
      • 但是又莫名其妙搞出来一个问题,后面一直不能复现,后来又好了,一直无法复现(考虑问题复现时,使用备用方案)
      • 反正现在是正常的
    • 20230811 虚拟环境中搞jtop(jetson-stats)还是有亿点问题

参考文章

Python虚拟环境使用教程(以虚拟环境管理工具venv为例)(virtualenv、venv、pyenv、virtualenvwrapper、conda不同管理工具对比)

目录结构

在这里插入图片描述

步骤

安装venv

它会基于当前版本的python3来安装python3-venv

在这里插入图片描述

apt update && apt install python3.8-venv

查看python版本

执行python

在这里插入图片描述

创建虚拟环境

进入项目目录,执行:

python3 -m venv .venv-python3.8

(我把每个项目虚拟环境固定取名为.venv-python3.8,后续方便脚本操作)

20230813:改了,不这么搞了,容易混淆,每个虚拟环境都应该有自己特定的名字:

python3 -m venv .venv-python3.8-ky_ai_ip_change

在这里插入图片描述

可以看到,生成了目录.venv-python3.8

我这刚生成的虚拟环境占空间也不大,才7兆多:

在这里插入图片描述

激活虚拟环境

source .venv-python3.8/bin/activate

在这里插入图片描述

运行我们程序看缺少哪些依赖库,依次安装它们

执行:

python3 ip_change

在这里插入图片描述

发现少了ping3,装上:

pip install ping3

在这里插入图片描述

反复执行:

python3 ip_change

缺少啥库就装啥库:

在这里插入图片描述

下载太慢,我换成清华源,怎么还给我卡住了?

pip install -i https://pypi.tuna.tsinghua.edu.cn/simple gevent

20230813:如果有requirements.txt文件,可以直接:

pip install -i https://pypi.tuna.tsinghua.edu.cn/simple -r requirements.txt

可以禁用缓存,因为缓存可能会导致大问题(比如缓存里有但是是用之前正确的方式下载的,当前下载方式不正确但用缓存也成功了,就会导致下载者误判):

pip install --no-cache-dir -i https://pypi.tuna.tsinghua.edu.cn/simple -r requirements.txt

在这里插入图片描述

第二天看,好了:

在这里插入图片描述

继续:

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

可以了,跑起来了,接口也能调通:

在这里插入图片描述
在这里插入图片描述

接下来我们配置python程序启动脚本,脚本中启动python程序前需先激活虚拟环境

注意journalctl -u <servicename>没有及时打印python日志的原因是因为在systemd unit文件中执行shell脚本,脚本中再执行python命令,命令没加-u参数导致的。估计是systemd自动把shell脚本输出重定向到journalctl日志,跟我们之前遇到的问题一样

ky_ai_ip_change.sh

#!/bin/bash

# 打印所有,包括注释
# set -v
# 打印执行命令
# set -x
# 命令出错退出
set -e
# 使用未初始化变量退出
set -u

USER="root"

# --------------------------------------------------------------------------

# 检查是否是root
WHO=$(whoami | grep "${USER}$")
if [ -z "${WHO}" ]; then
    echo
    echo "Please change to \"${USER}\" user mode first!"
    echo
    exit 1
fi

# --------------------------------------------------------------------------

# 获取脚本所在路径
SCRIPT_LOCATION=$(
    cd "$(dirname "$0")" || {
        echo "cd Failure"
        exit 1
    }
    pwd
)
echo "SCRIPT_LOCATION = $SCRIPT_LOCATION"

# --------------------------------------------------------------------------

VENV_NAME=".venv-python3.8"
PYTHON_ENTRY_FILE="ip_change"

# --------------------------------------------------------------------------

# 激活虚拟环境
# 加指令注释消除shellcheck警告,source后有变量就会警告
# shellcheck source=/ky/tml/ky_ai_ip_change/.venv-python3.8/bin/activate
source $SCRIPT_LOCATION/$VENV_NAME/bin/activate
if [ $? -ne 0 ]; then
    echo "Execute [source $SCRIPT_LOCATION/$VENV_NAME/bin/activate] failed"
    exit 1
fi

# 运行项目
# python -u $SCRIPT_LOCATION/$PYTHON_ENTRY_FILE
# if [ $? -ne 0 ]; then
#     echo "Execute [python $SCRIPT_LOCATION/$PYTHON_ENTRY_FILE] failed"
#     exit 1
# fi

# 改一改,避免命令报错直接退出脚本,没有机会退出虚拟环境
if python -u $SCRIPT_LOCATION/$PYTHON_ENTRY_FILE; then
    echo "命令 [python -u $SCRIPT_LOCATION/$PYTHON_ENTRY_FILE] 执行成功"
else
    echo "命令 [python -u $SCRIPT_LOCATION/$PYTHON_ENTRY_FILE] 执行失败"
fi

deactivate
if [ $? -ne 0 ]; then
    echo "Execute [deactivate] failed,退出虚拟环境失败"
    exit 1
fi
echo "Execute [deactivate] successfully,退出虚拟环境成功"

配置.service文件

ky_ai_ip_change.service

[Unit]
Description=ky_ai_ip_change
After=network.target

[Service]
ExecStart=/ky/tml/ky_ai_ip_change/ky_ai_ip_change.sh
WorkingDirectory=/ky/tml/ky_ai_ip_change
Restart=always
RestartSec=3

[Install]
WantedBy=default.target

然后执行部署脚本,成功了

install.sh

#!/bin/bash

# 打印所有,包括注释
# set -v
# 打印执行命令
# set -x
# 命令出错退出
set -e
# 使用未初始化变量退出
set -u

USER=root
# USER_HOME=/root

# --------------------------------------------------------------------------

# 检查是否是root
WHO=$(whoami | grep "${USER}$")
if [ -z "${WHO}" ]; then
    echo
    echo "Please change to \"${USER}\" user mode first!"
    echo
    exit 1
fi

# --------------------------------------------------------------------------

# 获取脚本所在路径
SCRIPT_LOCATION=$(
    cd "$(dirname "$0")" || {
        echo "cd Failure"
        exit 1
    }
    pwd
)
# echo "SCRIPT_LOCATION = $SCRIPT_LOCATION"
chmod 777 ${SCRIPT_LOCATION} -R

# --------------------------------------------------------------------------

# 不同服务只用改 SERVICE_NAME 变量即可
SERVICE_NAME="ky_ai_ip_change"
SERVICE_FILE_NAME="$SERVICE_NAME.service"

SERVICE_SOURCE_FILE_PATH="$SCRIPT_LOCATION/$SERVICE_FILE_NAME"

# 不能在 /etc/systemd/system 中创建子目录吗?(貌似是的,测试很多次都不行)
# SERVICE_TARGET_DIR_NAME="ky_ai_service"
# SERVICE_TARGET_DIR_PATH="/etc/systemd/system/$SERVICE_TARGET_DIR_NAME"
SERVICE_TARGET_DIR_PATH="/etc/systemd/system"

# --------------------------------------------------------------------------

# 创建目标目录
# if [ ! -d "$SERVICE_TARGET_DIR_PATH" ]; then
#     mkdir -p "$SERVICE_TARGET_DIR_PATH"
#     echo "创建目录:[$SERVICE_TARGET_DIR_PATH]"
# else
#     echo "目录已存在,不重新创建:[$SERVICE_TARGET_DIR_PATH]"
# fi
# chmod 777 "$SERVICE_TARGET_DIR_PATH" -R

# --------------------------------------------------------------------------

# 判断服务是否存在
if systemctl list-unit-files --type=service | grep -q "$SERVICE_NAME"; then
    echo "$SERVICE_NAME.service exists"
    # 打印服务状态
    # systemctl status $SERVICE_NAME
    echo
    # 这句明明是打印居然会触发 set -e 报错退出,加上 || true
    # systemctl status $SERVICE_NAME || true
    # 貌似信息比较长时,会有分页等待用户输入阻塞程序,加上 --no-pager 选项
    systemctl status $SERVICE_NAME --no-pager || true
    echo
    # 询问用户是否删除
    read -p "Do you want to delete $SERVICE_NAME.service? (y/n): " choice
    if [[ $choice == "y" || $choice == "Y" ]]; then
        # 删除服务
        systemctl stop $SERVICE_NAME
        echo "已 stop [$SERVICE_NAME] 服务 "
        systemctl disable $SERVICE_NAME
        echo "已 disable [$SERVICE_NAME] 服务"
        # rm /etc/systemd/system/$SERVICE_NAME.service  # 不用删,会自动删的
        systemctl daemon-reload
        echo "已 daemon-reload"
        echo "$SERVICE_NAME.service has been deleted"
    else
        echo "Exiting script"
        exit 0
    fi
else
    echo "$SERVICE_NAME.service not exists"
fi
echo

# --------------------------------------------------------------------------

# 这句明明是打印居然会触发 set -e 报错退出
# systemctl list-unit-files | grep "$SERVICE_NAME"
# systemctl list-unit-files | grep "$SERVICE_NAME" || true

# --------------------------------------------------------------------------

# Function: create_symlink
# Description: Check if a symlink exists and is valid. If it is valid, prompt the user to delete and relink it.
#              If it is invalid, display an error message. If it does not exist, create a new symlink.
# Parameters:
#   $1 - The target path of the symlink
#   $2 - The path of the symlink
# Returns:
#   None

function create_symlink() {
    SRC=$1
    LINK=$2

    if [ -e $LINK ]; then
        if [ -L $LINK ]; then
            echo "The symlink $LINK is valid."
            read -p "Do you want to delete and relink it? (y/n) " choice
            case "$choice" in
            y | Y)
                rm $LINK
                echo "The symlink $LINK has been deleted."
                ;;
            *)
                return 0
                ;;
            esac
        else
            echo "The symlink $LINK is invalid."
        fi
    fi
    echo "Force create soft link: [$LINK -> $SRC]"
    ln -sf $SRC $LINK
    if [ $? -ne 0 ]; then
        echo "Force create soft link: [$LINK -> $SRC] failed"
        exit 1
    fi
    ls -l --color=auto $LINK
}

# --------------------------------------------------------------------------

# 判断软链接/usr/local/bin/node是否存在,如果存在,判断软链接是否有效,如果有效,询问用户是否删除,如果用户选择是,则删除此软链接,并重新创建
SERVICE_TARGET_FILE_PATH="$SERVICE_TARGET_DIR_PATH/$SERVICE_FILE_NAME"
# ls -l --color=auto $NODE_LINK
create_symlink $SERVICE_SOURCE_FILE_PATH $SERVICE_TARGET_FILE_PATH
echo

# --------------------------------------------------------------------------

# 通知systemd重新加载配置文件
systemctl daemon-reload
if [ $? -ne 0 ]; then
    echo "Systemctl daemon-reload failed"
    exit 1
fi
echo "Daemon-reload successfully"

# 启用服务
systemctl enable $SERVICE_NAME
if [ $? -ne 0 ]; then
    echo "Enable service [$SERVICE_NAME] failed"
    exit 1
fi
echo "Enable service [$SERVICE_NAME] successfully"

# 启动服务
systemctl start $SERVICE_NAME
if [ $? -ne 0 ]; then
    echo "Start service [$SERVICE_NAME] failed"
    exit 1
fi
echo "Start service [$SERVICE_NAME] successfully"

# --------------------------------------------------------------------------

echo
# systemctl status $SERVICE_NAME || true
# 貌似信息比较长时,会有分页等待用户输入阻塞程序,加上 --no-pager 选项
systemctl status $SERVICE_NAME --no-pager || true

# --------------------------------------------------------------------------

echo
echo "Service [$SERVICE_FILE_NAME] install successfully"
echo

但是又莫名其妙搞出来一个问题,后面一直不能复现,后来又好了,一直无法复现(考虑问题复现时,使用备用方案)

参考文章:Current command vanished from the unit file, execution of the command list won‘t be resumed.

后面如果又碰到,可以考虑直接systemd unit文件中直接执行python指令而不是脚本,同时定义ExecStartPreExecStopPost执行指令前的激活虚拟环境和退出虚拟环境的操作:


如果使用systemd来执行Python服务,可以在service配置文件中设置ExecStartPreExecStopPost来在执行前进入虚拟环境,执行后退出虚拟环境。

以下是一个示例的service配置文件,展示了如何在执行前进入虚拟环境,执行后退出虚拟环境:

[Unit]
Description=My Python Service

[Service]
ExecStartPre=/bin/bash -c 'source /path/to/venv/bin/activate'
ExecStart=/path/to/python /path/to/script.py
ExecStopPost=/bin/bash -c 'deactivate'

[Install]
WantedBy=multi-user.target

在这个示例中,ExecStartPre指定了在执行前要执行的命令,即进入虚拟环境的命令source /path/to/venv/bin/activateExecStart指定了要执行的Python脚本的路径。ExecStopPost指定了在执行后要执行的命令,即退出虚拟环境的命令deactivate

请将/path/to/venv替换为你的虚拟环境的路径,将/path/to/python替换为你的Python解释器的路径,将/path/to/script.py替换为你的Python脚本的路径。

通过这样的配置,当你启动或停止该service时,会自动进入和退出虚拟环境。

反正现在是正常的

在这里插入图片描述
在这里插入图片描述

20230811 虚拟环境中搞jtop(jetson-stats)还是有亿点问题

pip3 install -U jetson-stats

在这里插入图片描述

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/871525.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

PyQt5利用QTextEdit控件输入多行文本

1、总代码 #!/usr/bin/env python # -*- coding: utf-8 -*- import sys from PyQt5.QtWidgets import QApplication,QWidget from PyQt5 import QtCore, QtWidgetsclass Ui_Form(object):def setupUi(self, Form):Form.setObjectName("Form")Form.resize(320, 240)s…

KafkaStream:基本使用

简介&#xff1a; kafkaStream&#xff1a;提供了对存储在kafka中的数据进行流式处理和分析的功能 特点&#xff1a; KafkasSream提供了一个非常简单轻量的Library&#xff0c;它可以非常方便的嵌入到java程序中&#xff0c;也可以任何方式打包部署 入门案例&#xff1a; 1、…

在C++中怎么判断一个东西是左值还是右值

2023年8月13日&#xff0c;周日早上 #include <iostream>// 函数模板&#xff0c;根据参数类型判断是左值还是右值 template<typename T> void checkValueType(T&& arg) {if constexpr(std::is_lvalue_reference<T>())std::cout << "Expr…

运营商加速抢占云计算,5G带来更多利润,上半年躺赚近千亿

中国移动已率先公布了上半年的业绩&#xff0c;业绩显示它们正在加速抢占此前由互联网企业占据优势的云计算市场&#xff0c;不过最让它们开心的还是5G继续带动利润的高速增长&#xff0c;预计三大运营商今年上半年可以躺赚近千亿元。 中国移动无疑仍然是运营商行业的领头羊&am…

tampermonky插件安装

换了电脑&#xff0c;今天重新下载了tampermonky&#xff0c;哎&#xff0c;被自己气死的一上午。wwwww&#xff0c;最后发现最大的问题就是没有问题。 Edge能不用下载直接安装&#xff0c;但是何少 下载tampermonky&#xff0c;在谷歌程序扩展-chrome://extensions/ 添加解压…

VirtualBox 导致的系统蓝屏问题

1&#xff0c;操作系统win7,已经启动了结果蓝屏 2&#xff0c;进入操作系统的命令行模式删除virtualbox的相关目录可以启动&#xff0c;但是无法在控制面板卸载&#xff0c;只要点击卸载就会发生蓝屏 3&#xff0c;删除注册表的相关内容 4&#xff0c;导致无线网络链接受限&…

京东面试曝光:零点秒杀如何防止Redis雪崩崩溃?

大家好&#xff0c;我是你们的小米&#xff01;今天要和大家聊一个超有技术含量的话题&#xff0c;那就是如何应对零点秒杀活动下的Redis雪崩问题。在京东的面试题中&#xff0c;这个问题可是相当有挑战性哦&#xff01;废话不多说&#xff0c;咱们直接进入主题吧。 什么是雪崩…

Academic Inquiry|国外文献查找

一个失去了男子气概的人总有很多忧虑&#xff0c;这样就可以分散注意力&#xff0c;而不必为那件特别的羞耻而苦恼不堪。 ——《狂野之夜》〔美〕乔伊斯卡罗尔欧茨著 樊维娜译 许多研究者在进行研究的时候&#xff0c;都会查找对应主体的国内外引用文献&#xff0c;而大多得出的…

2023杭州十大画室排行榜丨哪家画室是你的最佳选择?

美术&#xff0c;是一种表达&#xff0c;是一种情感的释放&#xff0c;也是一种对美的追求。而在杭州的画室&#xff0c;就是这种追求的最好舞台。接下来&#xff0c;我们将一起揭晓杭州十大画室&#xff0c;一起感受艺术的独特魅力&#xff0c;一起感受那种深入骨髓的艺术冲击…

2023/08/13_______JVM(CG)垃圾回收 算法(复制算法,标记清除,标记清除压缩)

JVM GC算法 复制算法 1&#xff0c;每一次GC都会将伊甸&#xff08;Eden&#xff09;活的对象移到幸存区中&#xff1a;一旦Eden区被GC后 就会是空 只要有内容就是from区 谁空谁是to区 内存会从 伊甸->幸存区to->幸存from&#xff08;这个时候to和from交换区域&#xf…

STM32入门学习之定时器输入捕获

1.定时器的输入捕获可以用来测量脉冲宽度或者测量频率。输入捕获的原理图如下&#xff1a; 假设定时器是向上计数。在图中&#xff0c;t1~t2之间的便是我们要测量的高电平的时间(脉冲宽度)。首先&#xff0c;设置定时器为上升沿捕获&#xff0c;如此一来&#xff0c;在t1时刻可…

C语言刷题训练【第十天】

大家好&#xff0c;我是纪宁。 今天是C语言刷题训练的第十天&#xff0c;加油&#xff01; 文章目录 &#x1f386;1、求函数返回值&#xff0c;传入 -1 &#xff0c;则在64位机器上函数返回&#xff08; &#xff09;&#x1f3a4;2、读代码选结果&#xff08; &#xff09;&…

8.13树的总结(有新知识再更新)

二叉树题目几个重点&#xff1a; 1. 理解递归&#xff0c;优先掌握递归实现 递归三部曲&#xff1a;1.确定递归函数的参数和返回类型&#xff1b;2.确定终止条件 &#xff1b;3.确定递归逻辑 因为递归一层一层对我来说有点绕&#xff0c;主要感悟就是只针对某一个节点思考&…

Mac思维导图软件Xmind for Mac中文激活版

好的思维导图软件能帮助用户更好的发挥创作能力&#xff0c;XMind是一款流行的思维导图软件&#xff0c;可以帮助用户创建各种类型的思维导图和概念图。 多样化的导图类型&#xff1a;XMind提供了多种类型的导图&#xff0c;如鱼骨图、树形图、机构图等&#xff0c;可以满足不同…

计算机视觉中的特征检测和描述

一、说明 这篇文章是关于计算机视觉中特征检测和描述概念的简要理解。在其中&#xff0c;我们探讨了它们的定义、常用技术、简单的 python 实现和一些限制。 二、什么是特征检测和描述&#xff1f; 特征检测和描述是计算机视觉中的基本概念&#xff0c;在图像识别、对象跟踪和图…

Seaborn图表使用指南!

目录 介绍线图散点图直方图概率密度函数 &#xff08;PDF&#xff09;箱线图小提琴剧情配对图热图关节图地毯图 一、介绍 数据科学已成为一个突出的领域&#xff0c;近年来呈爆炸性增长。对精通从数据中获取见解并应用这些见解来解决现实世界问题的数据科学家的需求从未增加。…

centos 7.x 单用户模式

最近碰到 centos 7.9 一些参数设置错误无法启动系统的情况&#xff0c;研究后可以使用单用户模式进入系统进行恢复操作。 进入启动界面&#xff0c;按 e ro 替换为 rw init/sysroot/bin/sh 替换前 替换后 Ctrl-x 进行重启进入单用户模式 执行 chroot /sysroot 可以查看日…

数据库操作不再困难,MyBatis动态Sql标签解析

系列文章目录 MyBatis缓存原理 Mybatis的CachingExecutor与二级缓存 Mybatis plugin 的使用及原理 MyBatis四大组件Executor、StatementHandler、ParameterHandler、ResultSetHandler 详解 MyBatisSpringboot 启动到SQL执行全流程 数据库操作不再困难&#xff0c;MyBatis动态S…