更好的方法:
https://askubuntu.com/questions/48321/how-do-i-start-applications-automatically-on-login

Non GUI approach
Advanced users may want to manually put a .desktop file in ~/.config/autostart to run applications after a user login. This may have following content:

[Desktop Entry]
Type=Application
Name=<Name of application as displayed>
Exec=<command to execute>
Icon=<full path to icon>
Comment=<optinal comments>
X-GNOME-Autostart-enabled=true

 如果要执行python程序,需要在python脚本里写上  #!/usr/bin/python   注释,表明是python程序。

比如要执行 testprocess.py ,其代码如下:

#!/usr/bin/python3

...

再创建一个shell 脚本文件 testprocess.sh,里面内容为,(为啥创建这个文件,似乎是 ~/.config/autostart/***.desktop 自动运行脚本只能执行shell script,不能执行可执行文件也不能执行python脚本文件):

#!/bin/sh

/home/nx/hzh/testprocess.py

最后其自动运行脚本如下 ~/.config/autostart/***.desktop   (自动运行脚本似乎只能执行shell script):

[Desktop Entry]
Type=Application
Name=monitor arm
Exec=/home/nx/hzh/testprocess2.sh
NoDisplay=true
# X-GNOME-Autostart-enabled=true

  

http://askubuntu.com/questions/9382/how-can-i-configure-a-service-to-run-at-startup
http://stackoverflow.com/questions/7221757/run-automatically-program-on-startup-under-linux-ubuntu






sudo mv /filename /etc/init.d/
sudo chmod +x /etc/init.d/filename 
sudo update-rc.d filename defaults

Script should now start on boot. Note that this method also works with both hard links and symbolic links (ln).

Edit

At this point in the boot process PATH isn't set yet, so it is critical that absolute paths are used throughout. BUT, as pointed out in the comments by Steve HHH, explicitly declaring the full file path (/etc/init.d/filename) for the update-rc.d command is not valid in most versions of Linux. Per the manpage for update-rc.d, the second parameter is a script located in /etc/init.d/*. Updated above code to reflect this.

Another Edit

Also as pointed out in the comments (by Charles Brandt), /filename must be an init style script. A good template was also provided - https://github.com/fhd/init-script-template.

Another link to another article just to avoid possible link rot (although it would be saddening if GitHub died) - http://www.linux.com/learn/tutorials/442412-managing-linux-daemons-with-init-scripts

yetAnother Edit

As pointed out in the comments (by Russell Yan), This works only on default mode of update-rc.d.

According to manual of update-rc.d, it can run on two modes, "the machines using the legacy mode will have a file /etc/init.d/.legacy-bootordering", in which case you have to pass sequence and runlevel configuration through command line arguments.

The equivalent argument set for the above example is

sudo update-rc.d filename start 20 2 3 4 5 . stop 20 0 1 6 .

  

  • To start a daemon at startup:
update-rc.d service_name defaults
  • To remove:
update-rc.d -f service_name remove

defaults => default run levels 2,3,4 and 5

Example:

update-rc.d tomcat7 defaults

1) 将你的启动脚本复制到 /etc/init.d目录下

以下假设你的脚本文件名为 test。

 

2) 设置脚本文件的权限

$ sudo chmod 755 /etc/init.d/test

 

3) 执行如下命令将脚本放到启动脚本中去:

$ cd /etc/init.d
$ sudo update-rc.d example_name.sh defaults 95

注:其中数字95是脚本启动的顺序号,按照自己的需要相应修改即可。在你有多个启动脚本,而它们之间又有先后启动的依赖关系时你就知道这个数字的具体作用了。该命令的输出信息参考如下:

update-rc.d: warning: /etc/init.d/example_name.sh missing LSB information
update-rc.d: see <http://wiki.debian.org/LSBInitScripts>
  Adding system startup for /etc/init.d/test ...
    /etc/rc0.d/K95example_name.sh -> ../init.d/example_name.sh
    /etc/rc1.d/K95example_name.sh -> ../init.d/example_name.sh
    /etc/rc6.d/K95example_name.sh -> ../init.d/example_name.sh
    /etc/rc2.d/S95example_name.sh -> ../init.d/example_name.sh
    /etc/rc3.d/S95example_name.sh -> ../init.d/example_name.sh
    /etc/rc4.d/S95example_name.sh -> ../init.d/example_name.sh
    /etc/rc5.d/S95example_name.sh -> ../init.d/example_name.sh

 

卸载启动脚本的方法:

$ cd /etc/init.d
 $ sudo update-rc.d -f example_name.sh

命令输出的信息参考如下:

Removing any system startup links for /etc/init.d/test ...
    /etc/rc0.d/K95example_name.sh
    /etc/rc1.d/K95example_name.sh
    /etc/rc2.d/S95example_name.sh
    /etc/rc3.d/S95example_name.sh
    /etc/rc4.d/S95example_name.sh
    /etc/rc5.d/S95example_name.sh
    /etc/rc6.d/K95example_name.sh

按指定顺序、在指定运行级别中启动或关闭

用法:

update-rc.d <basename> start|stop <order> <runlevels>

例:

# update-rc.d ushare start 20 2 3 4 5 . stop 20 0 1 6 .

解析:表示在2、3、4、5这五个运行级别中,由小到大,第20个开始运行ushare;在 0 1 6这3个运行级别中,第20个关闭apachectl。

注意它有2个点号,其效果等于下面方法:

# update-rc.d ushare defaults

设置启动和关闭顺序为80,20, 级别为默认值:

# update-rc.d <basename> defaults 80 20

 -------------------------------------------------------------

linux中的init版本介绍:

init类型

说明

识别

Systemd

新出现的init,很多linux发行版都已经或者计划转向Systemd

如果你的系统目录文件中/usr/lib/systemd和/etc/systemd,说明你有systemd,ubuntu自从15.04版本以后都使用了systemd

Upstart

ubuntu曾经使用的init,但是现在已经转向了systemd

系统目录有/etc/init,而且其中有许多conf文件,说明你的系统有upstart(除非你的系统是debian7,那说明你使用的是System V init),同时,ubuntu 17.10也有这个目录,我猜测可能是为了兼容(此处存疑问,现在的ubuntu的init确实是systemd)

System V init

传统的init,大多数的linux发行版都会兼容

系统有/etc/inittab文件,说明你很可能是System V init

update-rc.d 命令


  1. 说明:安装或者移除 System-V init的脚本连接(可以理解为指向脚本的快捷方式,即 /etc/rc*runlevel*.d/NNname => /etc/init.d/name)。你可以通过runlevel命令查看当前的运行级别,runlevel的概念网上一大堆就不提及了。简单来说,假如我的机器开机默认会进入runlevel为5的空间(ubuntu图形界面),那么就会在开机后执行/etc/rc5.d/*下所有的脚本(这样描述有些误差,其实此目录下都是软链接,指向/etc/init.d/下相对应的脚本)。另外,你还会发现这些链接的命名规则很有意思,一般来说,K开头的链接是关闭这个服务,而S开头的才是启动这个服务。此时应该有疑问,为什么链接都是指向同一个脚本,但是功能确是截然相反?网上有人说是这两个字母给脚本传递了不同的参数,但其实这个过程怎么实现我还不是很清楚(可以cat一下/etc/init.d/rsyslog的内容,这个shell脚本思路还是很清晰的,先是定义了各种函数,然后通过参数$1运用case语句来调用不同的函数,此时你会发现 service serv_name COMMAND其实和 /etc/init.d/serv_name COMMAND是一样的)
  2. 简单来说,你可以通过此命令控制开机自启动服务。
  • 开机启动服务(建立软链接): update-rc.d foobar defaults
  • 移除所有软链接:update-rc.d foobar remove
  • 关闭开机启动服务:update-rc.d foobar disable
  • 重新开启开机启动服务:update-rc.d foobar enable

 

Systemd介绍:  (以下内容大部分来自 http://www.ruanyifeng.com/blog/2016/03/systemd-tutorial-commands.html, http://www.ruanyifeng.com/blog/2016/03/systemd-tutorial-part-two.html)

历史上,Linux 的启动一直采用init进程。

下面的命令用来启动服务。

$ sudo /etc/init.d/apache2 start
# 或者
$ service apache2 start

这种方法有两个缺点。

一是启动时间长。init进程是串行启动,只有前一个进程启动完,才会启动下一个进程。

二是启动脚本复杂。init进程只是执行启动脚本,不管其他事情。脚本需要自己处理各种情况,这往往使得脚本变得很长。

 Systemd 就是为了解决这些问题而诞生的。它的设计目标是,为系统的启动和管理提供一套完整的解决方案。Systemd 并不是一个命令,而是一组命令,涉及到系统管理的方方面面。

systemctl是 Systemd 的主命令,用于管理系统。

systemd-analyze命令用于查看启动耗时。

hostnamectl命令用于查看当前主机的信息。

localectl命令用于查看本地化设置。

timedatectl命令用于查看当前时区设置。

loginctl命令用于查看当前登录的用户。

Unit

Systemd 可以管理所有系统资源。不同的资源统称为 Unit,unit可以叫做服务单元。

Unit 一共分成12种。

  • Service unit:系统服务
  • Target unit:多个 Unit 构成的一个组
  • Device Unit:硬件设备
  • Mount Unit:文件系统的挂载点
  • Automount Unit:自动挂载点
  • Path Unit:文件或路径
  • Scope Unit:不是由 Systemd 启动的外部进程
  • Slice Unit:进程组
  • Snapshot Unit:Systemd 快照,可以切回某个快照
  • Socket Unit:进程间通信的 socket
  • Swap Unit:swap 文件
  • Timer Unit:定时器

systemctl list-units命令可以查看当前系统的所有 Unit 。

systemctl status命令用于查看系统状态和单个 Unit 的状态。

除了status命令,systemctl还提供了三个查询状态的简单方法,主要供脚本内部的判断语句使用。

# 显示某个 Unit 是否正在运行
$ systemctl is-active application.service

# 显示某个 Unit 是否处于启动失败状态
$ systemctl is-failed application.service

# 显示某个 Unit 服务是否建立了启动链接
$ systemctl is-enabled application.service

最常用的是下面这些命令,用于启动和停止 Unit(主要是 service):

# 立即启动一个服务
$ sudo systemctl start apache.service

# 立即停止一个服务
$ sudo systemctl stop apache.service

# 重启一个服务
$ sudo systemctl restart apache.service

# 杀死一个服务的所有子进程
$ sudo systemctl kill apache.service

# 重新加载一个服务的配置文件
$ sudo systemctl reload apache.service

# 重载所有修改过的配置文件
$ sudo systemctl daemon-reload

# 显示某个 Unit 的所有底层参数
$ systemctl show httpd.service

# 显示某个 Unit 的指定属性的值
$ systemctl show -p CPUShares httpd.service

# 设置某个 Unit 的指定属性
$ sudo systemctl set-property httpd.service CPUShares=500

Target

启动计算机的时候,需要启动大量的 Unit。如果每一次启动,都要一一写明本次启动需要哪些 Unit,显然非常不方便。Systemd 的解决方案就是 Target。

简单说,Target 就是一个 Unit 组,包含许多相关的 Unit 。启动某个 Target 的时候,Systemd 就会启动里面所有的 Unit。

传统的init启动模式里面,有 RunLevel 的概念,跟 Target 的作用很类似。不同的是,RunLevel 是互斥的,不可能多个 RunLevel 同时启动,但是多个 Target 可以同时启动。

Target 与 传统 RunLevel 的对应关系如下。

Traditional runlevel      New target name     Symbolically linked to...

Runlevel 0           |    runlevel0.target -> poweroff.target
Runlevel 1           |    runlevel1.target -> rescue.target
Runlevel 2           |    runlevel2.target -> multi-user.target
Runlevel 3           |    runlevel3.target -> multi-user.target
Runlevel 4           |    runlevel4.target -> multi-user.target
Runlevel 5           |    runlevel5.target -> graphical.target
Runlevel 6           |    runlevel6.target -> reboot.target

它与init进程的主要差别如下。

(1)默认的 RunLevel(在/etc/inittab文件设置)现在被默认的 Target 取代,位置是/etc/systemd/system/default.target,通常符号链接到graphical.target(图形界面)或者multi-user.target(多用户命令行)。

(2)启动脚本的位置,以前是/etc/init.d目录,符号链接到不同的 RunLevel 目录 (比如/etc/rc3.d/etc/rc5.d等),现在则存放在/lib/systemd/system/etc/systemd/system目录。

(3)配置文件的位置,以前init进程的配置文件是/etc/inittab,各种服务的配置文件存放在/etc/sysconfig目录。现在的配置文件主要存放在/lib/systemd目录,在/etc/systemd目录里面的修改可以覆盖原始设置。

日志管理

Systemd 统一管理所有 Unit 的启动日志。带来的好处就是,可以只用journalctl一个命令,查看所有日志(内核日志和应用日志)。日志的配置文件是/etc/systemd/journald.conf

journalctl功能强大,用法非常多。

# 查看所有日志(默认情况下 ,只保存本次启动的日志)
$ sudo journalctl

# 查看内核日志(不显示应用日志)
$ sudo journalctl -k

# 查看系统本次启动的日志
$ sudo journalctl -b
$ sudo journalctl -b -0

# 查看上一次启动的日志(需更改设置)
$ sudo journalctl -b -1

# 查看指定时间的日志
$ sudo journalctl --since="2012-10-30 18:17:16"
$ sudo journalctl --since "20 min ago"
$ sudo journalctl --since yesterday
$ sudo journalctl --since "2015-01-10" --until "2015-01-11 03:00"
$ sudo journalctl --since 09:00 --until "1 hour ago"

# 显示尾部的最新10行日志
$ sudo journalctl -n

# 显示尾部指定行数的日志
$ sudo journalctl -n 20

# 实时滚动显示最新日志
$ sudo journalctl -f

# 查看指定服务的日志
$ sudo journalctl /usr/lib/systemd/systemd

# 查看指定进程的日志
$ sudo journalctl _PID=1

# 查看某个路径的脚本的日志
$ sudo journalctl /usr/bin/bash

# 查看指定用户的日志
$ sudo journalctl _UID=33 --since today

# 查看某个 Unit 的日志
$ sudo journalctl -u nginx.service
$ sudo journalctl -u nginx.service --since today

# 实时滚动显示某个 Unit 的最新日志
$ sudo journalctl -u nginx.service -f

# 合并显示多个 Unit 的日志
$ journalctl -u nginx.service -u php-fpm.service --since today

# 查看指定优先级(及其以上级别)的日志,共有8级
# 0: emerg
# 1: alert
# 2: crit
# 3: err
# 4: warning
# 5: notice
# 6: info
# 7: debug
$ sudo journalctl -p err -b

# 日志默认分页输出,--no-pager 改为正常的标准输出
$ sudo journalctl --no-pager

# 以 JSON 格式(单行)输出
$ sudo journalctl -b -u nginx.service -o json

# 以 JSON 格式(多行)输出,可读性更好
$ sudo journalctl -b -u nginx.serviceqq
 -o json-pretty

# 显示日志占据的硬盘空间
$ sudo journalctl --disk-usage

# 指定日志文件占据的最大空间
$ sudo journalctl --vacuum-size=1G

# 指定日志文件保存多久
$ sudo journalctl --vacuum-time=1years

 

systemd的启动

对于那些支持 Systemd 的软件,安装的时候,会自动在/usr/lib/systemd/system目录添加一个配置文件。

如果你想让该软件开机启动,就执行下面的命令(以httpd.service为例)。

$ sudo systemctl enable httpd

上面的命令相当于在/etc/systemd/system目录添加一个符号链接,指向/usr/lib/systemd/system里面的httpd.service文件。

这是因为开机时,Systemd只执行/etc/systemd/system目录里面的配置文件。这也意味着,如果把修改后的配置文件放在该目录,就可以达到覆盖原始配置的效果。

启动类型

Type字段定义启动类型。它可以设置的值如下。

  • simple(默认值):ExecStart字段启动的进程为主进程
  • forking:ExecStart字段将以fork()方式启动,此时父进程将会退出,子进程将成为主进程
  • oneshot:类似于simple,但只执行一次,Systemd 会等它执行完,才启动其他服务
  • dbus:类似于simple,但会等待 D-Bus 信号后启动
  • notify:类似于simple,启动结束后会发出通知信号,然后 Systemd 再启动其他服务
  • idle:类似于simple,但是要等到其他任务都执行完,才会启动该服务。一种使用场合是为让该服务的输出,不与其他服务的输出相混合

重启行为

Service区块有一些字段,定义了重启行为。

KillMode字段:定义 Systemd 如何停止 sshd 服务。

上面这个例子中,将KillMode设为process,表示只停止主进程,不停止任何sshd 子进程,即子进程打开的 SSH session 仍然保持连接。这个设置不太常见,但对 sshd 很重要,否则你停止服务的时候,会连自己打开的 SSH session 一起杀掉。

KillMode字段可以设置的值如下。

  • control-group(默认值):当前控制组里面的所有子进程,都会被杀掉
  • process:只杀主进程
  • mixed:主进程将收到 SIGTERM 信号,子进程收到 SIGKILL 信号
  • none:没有进程会被杀掉,只是执行服务的 stop 命令。

接下来是Restart字段。

Restart字段:定义了 sshd 退出后,Systemd 的重启方式。

上面的例子中,Restart设为on-failure,表示任何意外的失败,就将重启sshd。如果 sshd 正常停止(比如执行systemctl stop命令),它就不会重启。

Restart字段可以设置的值如下。

  • no(默认值):退出后不会重启
  • on-success:只有正常退出时(退出状态码为0),才会重启
  • on-failure:非正常退出时(退出状态码非0),包括被信号终止和超时,才会重启
  • on-abnormal:只有被信号终止和超时,才会重启
  • on-abort:只有在收到没有捕捉到的信号终止时,才会重启
  • on-watchdog:超时退出,才会重启
  • always:不管是什么退出原因,总是重启

对于守护进程,推荐设为on-failure。对于那些允许发生错误退出的服务,可以设为on-abnormal

最后是RestartSec字段。

RestartSec字段:表示 Systemd 重启服务之前,需要等待的秒数。上面的例子设为等待42秒。

[Install] 区块

Install区块,定义如何安装这个配置文件,即怎样做到开机启动。

WantedBy字段:表示该服务所在的 Target。

Target的含义是服务组,表示一组服务。WantedBy=multi-user.target指的是,sshd 所在的 Target 是multi-user.target

这个设置非常重要,因为执行systemctl enable sshd.service命令时,sshd.service的一个符号链接,就会放在/etc/systemd/system目录下面的multi-user.target.wants子目录之中。

Systemd 有默认的启动 Target。

$ systemctl get-default multi-user.target

上面的结果表示,默认的启动 Target 是multi-user.target。在这个组里的所有服务,都将开机启动。这就是为什么systemctl enable命令能设置开机启动的原因。

使用 Target 的时候,systemctl list-dependencies命令和systemctl isolate命令也很有用。

# 查看 multi-user.target 包含的所有服务 $ systemctl list-dependencies multi-user.target # 切换到另一个 target # shutdown.target 就是关机状态 $ sudo systemctl isolate shutdown.target

一般来说,常用的 Target 有两个:一个是multi-user.target,表示多用户命令行状态;另一个是graphical.target,表示图形用户状态,它依赖于multi-user.target。官方文档有一张非常清晰的 Target 依赖关系图

Target 的配置文件

Target 也有自己的配置文件。

$ systemctl cat multi-user.target [Unit] Description=Multi-User System Documentation=man:systemd.special(7) Requires=basic.target Conflicts=rescue.service rescue.target After=basic.target rescue.service rescue.target AllowIsolate=yes

注意,Target 配置文件里面没有启动命令。

上面输出结果中,主要字段含义如下。

Requires字段:要求basic.target一起运行。

Conflicts字段:冲突字段。如果rescue.servicerescue.target正在运行,multi-user.target就不能运行,反之亦然。

After:表示multi-user.targetbasic.target 、 rescue.service、 rescue.target之后启动,如果它们有启动的话。

AllowIsolate:允许使用systemctl isolate命令切换到multi-user.target

修改配置文件后重启

修改配置文件以后,需要重新加载配置文件,然后重新启动相关服务。

# 重新加载配置文件 $ sudo systemctl daemon-reload # 重启相关服务 $ sudo systemctl restart foobar 

 

 

 

systemd实现开机启动某程序软件

https://www.howtogeek.com/687970/how-to-run-a-linux-program-at-startup-with-systemd/

Creating the Service Program

We need to have a program that systemd will launch. We’ll create a simple script, called “htg.sh”. This tutorial uses the Gedit text editor, but you can use whatever text editor you prefer.

touch htg.sh
gedit htg.sh

The gedit editor will open. Copy and paste the following text into the editor.

#!/bin/bash

echo "htg.service: ## Starting ##" | systemd-cat -p info

while :
do
TIMESTAMP=$(date '+%Y-%m-%d %H:%M:%S')
echo "htg.service: timestamp ${TIMESTAMP}" | systemd-cat -p info
sleep 60
done

We’ll copy the script to the /usr/local/bin directory.

sudo cp htg.sh /usr/local/bin

And we need to make it executable:

sudo chmod +x /usr/local/bin/htg.sh

Creating the Service Unit File

list the service for show:

sudo systemctl list-unit-files --type-service

Our service is going to be called “htg.service”. No unit files have that name, so we can proceed and create our unit file.

sudo gedit /etc/systemd/system/htg.service

The gedit editor will open. Copy and paste the following text into the editor:

[Unit]
Description=How-To Geek Service Example

Wants=network.target
After=syslog.target network-online.target

[Service]
Type=simple
ExecStart=/usr/local/bin/htg.sh
Restart=on-failure
RestartSec=10
KillMode=process

[Install]
WantedBy=multi-user.target

This command will give the owner read and write permissions, and read permissions to the group. Others will have no permissions.

sudo chmod 640 /etc/systemd/system/htg.service

We can have systemctl check the syntax of our unit file for us, even if the service isn’t running yet. Any errors will be reported. (Actually, the “.service” part is optional for most commands.)

systemctl status htg.service

Starting the Service

When you add a new unit file or edit an existing one, you must tell systemd to reload the unit file definitions.

sudo systemctl daemon-reload

If you want a service to be launched at startup you must enable it:

sudo systemctl enable htg

Enabling a service doesn’t start it, it only sets it to be launched at boot time. To start the service now, you must use systemctl with the start option.

sudo systemctl start htg

Verifying the Service

After manually starting the service or after rebooting the computer, we can verify that our service is running correctly.

sudo systemctl status htg.service

Stopping and Disabling the Service

If you need to stop the service, you can do so with this command:

sudo systemctl stop htg.service

This stops the service, but it doesn’t prevent it from restarting next time the computer is rebooted. To stop the service being launched at startup, you need to disable it:

sudo systemctl disable htg.service

 

 

下面是一个较完整的示例:

https://askubuntu.com/questions/919054/how-do-i-run-a-single-command-at-startup-using-systemd

[Unit]
Description=Apache Spark Master and Slave Servers
After=network.target
After=systemd-user-sessions.service
After=network-online.target

[Service]
User=spark
Type=forking
ExecStart=/opt/spark-1.6.1-bin-hadoop2.6/sbin/start-all.sh
ExecStop=/opt/spark-1.6.1-bin-hadoop2.6/sbin/stop-all.sh
TimeoutSec=30
Restart=on-failure
RestartSec=30
StartLimitInterval=350
StartLimitBurst=10

[Install]
WantedBy=multi-user.target