Ubuntu设置开机自启动项,支持需要sudo的命令

对于Ubuntu桌面版及各种发行版,例如Zorin OS,可以使用“启动应用程序”图形界面工具添加开机启动项:

Zorin OS启动应用程序首选项

使用这个工具添加开机启动项实际上是在以下目录创建了启动器:

$HOME/.config/autostart

启动器的内容如下:

[Desktop Entry]
Type=Application
Exec=命令
Hidden=false
NoDisplay=false
X-GNOME-Autostart-enabled=true
Name[zh_CN]=名称
Name=名称
Comment[zh_CN]=描述
Comment=描述

事实上直接将.desktop文件拷贝到这个目录中也是等效的。

使用这种方式创建的开机启动项不能执行需要sudo的命令,尽管可以给要执行的脚本赋予可执行权限:

sudo chmod a+x path

相比之下,我更倾向于添加自启动服务。

Systemd的.service服务文件配置

.service文件的基本结构如下:

[Unit]
...
[Service]
...
[Install]
...

[Unit]块:

配置服务的启动顺序和依赖关系,示例:

[Unit]
Description=/etc/rc.local Compatibility
Documentation=man:systemd-rc-local-generator(8)
ConditionFileIsExecutable=/etc/rc.local
After=network.target

常用参数:

  • Description:对该服务的描述;
  • Documention:该服务的说明文档;
  • ConditionFileIsExecutable:指定执行文件,需要可执行权限;
  • Before:在其他服务启动前启动本服务;
  • After:在其他服务启动后再启动本服务;
  • Wants:弱依赖,即使被依赖服务启动失败或停止,本服务仍然运行;
  • Requires:强依赖,如果被依赖服务启动失败或停止,本服务也会停止。

[Service]块:

配置服务运行的方式,示例:

[Service]
Type=forking
ExecStart=/etc/rc.local start
TimeoutSec=0

常用参数:

  • EnvironmentFile:服务的参数文件;
  • ExecStart:服务启动时执行的命令;
  • ExecStop:服务停止时执行的命令;
  • Type:服务的启动类型;
  • TimeoutStartSec:服务允许的最大启动时长。如果守护进程未能在限定的时长内发出"启动完毕"的信号,那么该服务将被视为启动失败,并会被关闭。单位默认为s,可以指定其他时间单位;
  • TimeoutStopSec:服务允许的最大停止时长;
  • TimeoutSec:同时设置服务的最大启动和停止时长;
  • KillMode:服务停止类型;
  • Restart:服务重启类型;
  • RestartSec:间隔多久重启服务。

[Install]块:

配置服务所属服务组,示例:

[Install]
WantedBy=multi-user.target
Alias=rc-local.service

常用参数:

  • WantedBy:指定服务所在服务组;
  • Alias:服务别名。不指定的情况下,服务名为文件名称;

Systemd服务管理

Systemd默认从以下目录读取配置文件:

/etc/systemd/system/

但实际的.service文件都是放置在以下目录:

/usr/lib/systemd/system

建立符号链接:

sudo systemctl enable my.service

以上命令效果等同于:

sudo ln -s /usr/lib/systemd/system/my.service /etc/systemd/system/my.service

systemctl命令:

重新加载服务的配置文件:

sudo systemctl daemon-reload my.service

启动服务:

sudo systemctl start my.service

停止服务:

sudo systemctl stop my.service

重启服务:

sudo systemctl restart my.service

设置开机启动:

sudo systemctl enable my.service

禁用开机启动:

sudo systemctl disable my.service

一劳永逸开机自启动法

利用rc.local来实现开机自启动,编辑rc-local.service文件:

sudo gedit /usr/lib/systemd/system/rc-local.service

可以看到该配置文件缺少[Install]块,在末尾添加即可:

[Install]
WantedBy=multi-user.target

设置开机启动:

sudo systemctl enable rc-local.service

此时可以看到以下目录中添加了rc-local.service的符号链接:

/etc/systemd/system/multi-user.target.wants

创建rc.local文件:

sudo gedit /etc/rc.local

文件内容如下:

#!/bin/sh -e

# 要执行的命令
/opt/lampp/lampp startapache

exit 0

文件开头的内容必须是:

#!/bin/sh -e

这里简单说下#!/bin/sh与#!/bin/bash的区别:

  • #!/bin/sh相当于带有–posix标志的#!/bin/bash,即POSIX标准的bash;
  • #!/bin/sh如果某行代码出错,就不再继续往下执行。

#!/bin/sh -e 的作用:

  • 正常的shell脚本里,执行完一条命令会用$?去判断上一条命令的返回值。如果为0代表执行成功,则可以继续往下执行;如果非0则代表执行失败,此时应该退出脚本。
  • -e 的作用是脚本运行时,只要命令返回值为非0就会自动退出,而不再需要自己去加判断。

注意:在/etc/rc.local文件中执行的命令不再需要加sudo,另外如果是执行sh,需要在命令末尾加&符号

最后,必须给/etc/rc.local可执行权限:

sudo chmod a+x /etc/rc.local
阿里云