一、以普通用户运行
你需要使 jetson
用户能够在不输入密码的情况下执行 chmod
命令。你可以通过编辑 sudoers
文件来达到这个目的。打开一个终端,然后输入以下命令:
sudo visudo
然后在文件的末尾添加以下行:
jetson ALL = NOPASSWD: /bin/chmod
保存并关闭文件。现在 jetson
用户可以在不输入密码的情况下运行 sudo chmod
命令。
1.1 用服务启动脚本的方式
创建启动脚本,并在 startup.sh
脚本中添加更详细的错误输出。
1.11 简单的startup.sh
脚本:
#!/bin/bash
sudo chmod 777 /dev/ttyTHS1
python3 /home/jetson/DronePort/drone_port.py
1.12 记录运行过程中打印的信息的脚本
#!/bin/bash
echo "Starting script..." >> /home/jetson/DronePort/startup.log
echo "Setting permissions for /dev/ttyTHS1..." >> /home/jetson/DronePort/startup.log
sudo chmod 777 /dev/ttyTHS1 >> /home/jetson/DronePort/startup.log 2>&1
echo "Running drone_port.py..." >> /home/jetson/DronePort/startup.log
python3 /home/jetson/DronePort/drone_port.py >> /home/jetson/DronePort/startup.log 2>&1
echo "Script finished." >> /home/jetson/DronePort/startup.log
1.13 以日期的方式命名记录打印信息的文件,你可以使用 date
命令和格式字符串来生成当前日期,并用它来命名你的日志文件。以下是如何修改你的脚本:
#!/bin/bash
DATE=$(date +%Y-%m-%d)
LOGFILE="/home/jetson/DronePort/console_$DATE.log"
echo "Starting script..." >> $LOGFILE
echo "Setting permissions for /dev/ttyTHS1..." >> $LOGFILE
sudo chmod 777 /dev/ttyTHS1 >> $LOGFILE 2>&1
echo "Running drone_port.py..." >> $LOGFILE
python3 /home/jetson/DronePort/drone_port.py >> $LOGFILE 2>&1
echo "Script finished." >> $LOGFILE
在这个脚本中,date +%Y-%m-%d
会生成一个形如 2022-01-01
的日期字符串,然后这个字符串被保存在 DATE
变量中。然后,这个日期字符串被用来创建 LOGFILE
变量,它是日志文件的完整路径。之后,所有的日志输出都被重定向到这个文件。
注意,这个脚本每天都会创建一个新的日志文件,名字中包含当天的日期。如果你希望所有的日志都写入同一个文件,你可以去掉 DATE
变量,直接使用原来的日志文件路径。
然后创建服务启动脚本
[Unit]
Description=Start APP on Power On
After=network.target
[Service]
ExecStartPre=/bin/sleep 5
ExecStart=/home/jetson/DronePort/startup.sh
WorkingDirectory=/home/jetson
Restart=always
User=jetson
[Install]
WantedBy=multi-user.target
确保drone_port.py和startup.sh权限可执行!!!
1.2 直接用服务启动的方式
接下来,你可以在你的服务文件中添加一个 ExecStartPre
行来改变 /dev/ttyTHS1
的权限:
[Unit]
Description=Start APP on Power On
After=network.target
[Service]
ExecStartPre=/bin/sleep 5
ExecStartPre=/usr/bin/sudo /bin/chmod 777 /dev/ttyTHS1
ExecStart=/usr/bin/python3 /home/jetson/DronePort/drone_port.py
WorkingDirectory=/home/jetson
Restart=always
User=jetson
[Install]
WantedBy=multi-user.target
现在,当你的服务开始运行时,它会先等待5秒,然后改变 /dev/ttyTHS1
的权限,最后运行你的 drone_port.py
脚本。
确保drone_port.py权限可执行!!!
如果文件存在并且可执行,那么问题可能在于你的服务文件。在你的服务文件中,你应该使用完整的路径来指定要执行的 Python 解释器,例如
/usr/bin/python3
而不是python3
。你可以使用which python3
命令找到 Python
解释器的完整路径。
在 systemd 服务文件中,
[Install]
部分定义了如何"安装"这个服务,也就是当你使用systemctl enable
命令时,systemd 如何创建服务的启动链接。
WantedBy
选项定义了当你启用服务时应该创建什么类型的链接。这里的"target"是 systemd
的一个概念,大致相当于运行级别。当系统达到某个 target 时,所有 “wanted by” 这个 target 的服务都会被启动。
WantedBy=multi-user.target
:
这是在多用户模式下启动服务的常见设置。多用户模式通常指的是系统已经完成启动过程,所有常规服务都已启动,可以有多个用户登录。这个设置通常适用于服务器和运行后台服务的情况。
WantedBy=default.target
:default.target
通常是一个符号链接,指向系统默认启动的
target。在大多数系统上,default.target
都会链接到multi-user.target
或
graphical.target
。graphical.target
和multi-user.target
类似,但还包括图形界面。如果你不确定应该使用哪个 target,那么default.target
通常是一个安全的选择。
总的来说,这两个设置的区别主要在于你的服务应该在系统启动的什么阶段开始运行。在大多数情况下,两者的效果是一样的。如果你的服务需要图形界面,那么你应该使用
graphical.target
或default.target
。如果你的服务是一个后台服务,那么
multi-user.target
通常是一个更好的选择。
两种方法都可以实现开机自启动 Python 代码,但哪种方法更好取决于你的具体需求。 直接用服务启动 Python
代码:这种方法更简单,更易于管理,因为你只需要维护一个服务文件。你可以直接在服务文件的ExecStart
中指定 Python
解释器和你的脚本的路径。这种方法的缺点是,如果你的 Python 脚本需要一些特殊的环境设置,你可能需要在服务文件中添加额外的配置。
用服务启动.sh
文件,然后在.sh
文件中启动 Python 代码:这种方法更灵活,因为你可以在.sh
文件中执行任何你需要的设置,然后启动 Python 代码。例如,你可以设置环境变量,启动其他程序,然后最后启动你的 Python
代码。这种方法的缺点是,你需要管理两个文件(服务文件和.sh
文件),并确保.sh
文件有执行权限。 如果你的 Python
脚本不需要特殊的环境设置,或者你希望尽可能简化配置,那么直接用服务启动 Python
代码可能是更好的选择。如果你的脚本需要一些特殊的设置,或者你需要更大的灵活性,那么用服务启动.sh
文件可能是更好的选择。
二、以root用户运行
2.1 用服务启动脚本的方式
2.11 编写startup.sh
脚本
#!/bin/bash
python3 /home/jetson/DronePort/drone_port.py
如果要记录运行过程中打印的信息,方式和上面1.12和1.13一样,不过不用在脚本中设置权限,也就是下面这句不用sudo chmod 777 /dev/ttyTHS1
2.2 编写服务,在[Service]
段添加User=root
来以root
用户身份运行这个服务。例如:
[Unit]
Description=Start APP on Power On
After=network.target
[Service]
ExecStartPre=/bin/sleep 5
ExecStart=/home/jetson/DronePort/startup.sh
WorkingDirectory=/home/jetson
Restart=always
User=root
[Install]
WantedBy=multi-user.target
2.2 直接用服务启动
[Unit]
Description=Start APP on Power On
After=network.target
[Service]
ExecStartPre=/bin/sleep 5
ExecStart=/usr/bin/python3 /home/jetson/DronePort/drone_port.py
WorkingDirectory=/home/jetson
Restart=always
User=root
[Install]
WantedBy=multi-user.target