Linux
软件工具使用

nohup、service和systemctl命令

简介:nohup、service和systemctl命令是Linux提供的用于启动脚本服务的三个命令

1. nohup及2>&1的用法

当我们在Linux服务器上使用类似于./start.sh的脚本启动服务后,控制台会停留在服务启动后的输出状态下,此时如果点击Ctrl + C或当SSH连接断开后启动的服务也会直接停掉。其实在这种情况下,我们可以使用nohup命令启动脚本,比如./start.sh >> nohup.log 2>&1 &,在这种模式下,服务启动后会在后台运行,不会停止,且命令行也会直接回到等待输入的状态。nohup命令的解释如下:

  • 用途:不挂断地运行命令。
  • 语法:nohup Command [ Arg … ] [ & ]
  • 描述:nohup命令运行由Command参数和任何相关的Arg参数指定的命令,忽略所有挂断(SIGHUP)信号。在注销后使用nohup命令运行后台中的程序。要运行后台中的nohup命令,添加&( 表示“and”的符号)到命令的尾部。

在操作系统中有三个常用的流,分别用0、1、2三个数字代替:

  • 0:标准输入流,即stdin
  • 1:标准输出流,即stdout
  • 2:标准错误流,即stderr

一般当我们用> console.log,实际是1 > console.log的省略用法;< console.log,实际是0 < console.log的省略用法;>>也类似。

所以在上面的命令./start.sh >> nohup.log 2>&1 &,有如下解释:

  1. 使用&结尾的命令启动的脚本服务,即使Terminal(终端)关闭后依然会保持运行;
  2. >> nohup.log实际是1 >> nohup.log的省略用法,即将标准输出追加到当前路径下nohup.log文件中;
  3. 2>&1的意思是把标准错误(2)重定向到标准输出中(1),而标准输出又输出到文件nohup.log里面,所以结果是将标准错误和标准输出都输出到文件nohup.log里面了。至于为什么需要将标准错误重定向到标准输出的原因,那是因为标准错误stderr没有缓冲区,而stdout有。这就会导致> nohup.log2 > nohup.log中的文件nohup.log被两次打开,而stdout和stderr将会竞争覆盖,这是错误的做法。

扩展:/dev/null文件的作用,这是一个无底洞,任何东西都可以定向到这里,但是却无法打开。所以一般当存在很大的stdou和stderr无用输出时,可以利用stdout和stderr定向到这里,如./command.sh > /dev/null 2>&1

2. service和systemctl命令

主流的Linux大多使用init.d或systemd来注册服务。

以CentOS 6.6为例,使用init.d部署和注册服务的使用方式如下:

首先将Java程序打成jar包,在build.gradle配置文件中加spring-boot-gradle-plugin插件,具体配置如下(配置完成后刷新gradle项目):

  • plugins {
  • id 'org.springframework.boot' version '1.5.4.RELEASE'
  • }
  • springBoot {
  • executable = true
  • }

然后在build.gradle所在的目录下运行命令gradle build进行打包,假设我们的项目名为test,此时在/build/libs目录下应该会有test.jar和test.jar.original两个jar包;test.jar是Java程序的可执行jar包,里面含有程序所用的依赖包

然后打成的test.jar包上传到服务器,例如路径/var/app/下,然后使用命令chmod +x test.jar将jar包设置成可执行文件。

接下来需要在在/etc/init.d下创建软链接:

  • $ sudo ln -s /var/app/test.jar /etc/init.d/test

其中test就是服务名,此时就可以使用service命令来管理服务了:

  • service test start:启动服务
  • service test stop:停止服务
  • service test status:服务状态
  • chkconfig test on:开机启动

    如果出现unable to find java提示信息,则说明缺少JAVA_HOME环境属性,可以设置服务器的环境变量,也可以制定配置文件;制定配置文件名必须和jar包的文件名相同,后缀必须是.conf,即本例中可以使用test.conf,将test.conf文件和jar文件放在同一目录下,然后在其中写入JAVA_HOME的路径内容如下:
  • JAVA_HOME=/opt/jdk1.8.0_121

以CentOS 7.1为例,使用systemd部署和注册服务的使用方式如下:

在/usr/lib/systemd/system/目录下新建文件test.service,填入下面内容:

  • [Unit]
  • Description=Test Systemctl Service Use Java
  • Documentation=https://blog.coderap.com
  • After=network.target
  • [Service]
  • User=centos
  • #Type=forking
  • PIDFile=/run/test.pid
  • ExecStart=/bin/sh -c '/usr/bin/java -jar /var/app/test.jar >> /var/log/test.log 2>&1'
  • SuccessExitStatus=143
  • TimeoutStopSec=10
  • Restart=on-failure
  • RestartSec=5
  • [Install]
  • WantedBy=multi-user.target

这里需要注意的是,我们是使用centos用户来启动服务的,因此需要将test.jar和test.log两个文件的拥有者和拥有者组修改为centos,使用命令chown centos:centos /var/app/test.jarchown centos:centos /var/log/test.log

设置之后,就可以使用systemctl命令来管理服务了:

  • systemctl start testsystemctl start test.service:启动服务
  • systemctl stop testsystemctl stop test.service:停止服务
  • systemctl status testsystemctl status test.service:服务状态
  • systemctl enable testsystemctl enable test.service:开机启动
  • journalctl -u testjournalctl -u test.service:查看服务日志