在Linux系统中,服务通常指在后台持续运行、无需用户交互的程序,而进程号(PID,Process ID)是操作系统为每个进程分配的唯一标识符,用于管理进程的生命周期(如终止、监控等),启动服务并获取其PID是系统管理和运维的基础操作,本文将详细介绍通过不同方式启动服务及对应PID的获取方法。
通过systemd管理服务(现代Linux主流方式)
systemd是目前大多数Linux发行版(如Ubuntu 16.04+、CentOS 7+)的默认系统管理器,通过单元文件(.service)定义服务的启动、停止等行为,并支持依赖管理、并行启动等高级功能。
创建/编辑服务文件
服务文件通常位于/etc/systemd/system/
目录下,例如创建一个名为myapp.service
的服务文件:
[Unit] Description=My Custom Application After=network.target [Service] Type=simple ExecStart=/usr/local/bin/myapp PIDFile=/var/run/myapp.pid User=myuser Group=mygroup Restart=on-failure [Install] WantedBy=multi-user.target
关键字段说明:
ExecStart
:服务启动命令(需绝对路径);PIDFile
:指定PID文件路径,systemd通过该文件跟踪主进程PID;User/Group
:运行服务的用户和组(需存在);Restart
:进程退出后的重启策略(如on-failure
表示失败时重启)。
启动服务并获取PID
(1)重载systemd配置(新建/修改服务文件后需执行):
sudo systemctl daemon-reload
(2)启动服务(start
为立即启动,enable
为开机自启):
sudo systemctl start myapp.service # 启动服务 sudo systemctl enable myapp.service # 设置开机自启
(3)查看服务状态及PID:
sudo systemctl status myapp.service # 显示服务状态,包含主进程PID
输出示例:
● myapp.service - My Custom Application
Loaded: loaded (/etc/systemd/system/myapp.service; enabled; vendor preset: enabled)
Active: active (running) since [时间]; [时间] ago
Main PID: 1234 (myapp)
Tasks: 5 (limit: 1137)
Memory: 12.3M
CGroup: /system.slice/myapp.service
└─1234 /usr/local/bin/myapp
其中Main PID: 1234
即为服务主进程的PID。
(4)通过systemd命令直接获取PID:
sudo systemctl show --property MainPID myapp.service # 输出:MainPID=1234
通过System V init(传统服务管理方式)
在较老的Linux发行版(如CentOS 6、Debian 7)中,仍使用System V init(简称SysV)管理服务,服务脚本通常位于/etc/init.d/
目录下。
服务脚本示例
以/etc/init.d/myservice
为例,脚本需包含start
、stop
、status
等操作:
#!/bin/bash # chkconfig: 2345 80 20 # description: My custom service PIDFILE=/var/run/myservice.pid DAEMON=/usr/local/bin/myservice start() { if [ -f $PIDFILE ]; then echo "Service already running (PID: $(cat $PIDFILE))" return 1 fi echo "Starting $DAEMON..." $DAEMON & echo $! > $PIDFILE # 将后台进程PID写入文件 } stop() { if [ ! -f $PIDFILE ]; then echo "Service not running" return 1 fi PID=$(cat $PIDFILE) echo "Stopping $DAEMON (PID: $PID)..." kill $PID rm -f $PIDFILE } status() { if [ -f $PIDFILE ]; then PID=$(cat $PIDFILE) if ps -p $PID > /dev/null; then echo "Service running (PID: $PID)" else echo "Service not running (stale PID file)" rm -f $PIDFILE fi else echo "Service not running" fi } case "$1" in start) start ;; stop) stop ;; status) status ;; restart) stop; start ;; *) echo "Usage: $0 {start|stop|status|restart}" exit 1 esac
关键点:
- 脚本需可执行(
chmod +x /etc/init.d/myservice
); chkconfig
行定义运行级别(2345)和启动/停止优先级(80/20);- 变量获取后台执行命令的PID,并写入
PIDFile
。
启动服务并获取PID
(1)添加/删除服务(chkconfig管理):
sudo chkconfig --add myservice # 添加为系统服务 sudo chkconfig myservice on # 开机自启
(2)启动服务:
sudo service myservice start # 启动服务 sudo /etc/init.d/myservice start # 也可直接执行脚本
(3)查看服务状态及PID:
sudo service myservice status # 显示服务状态及PID
输出示例:
Service running (PID: 5678)
(4)通过PID文件获取PID:
cat /var/run/myservice.pid # 直接读取PID文件内容
直接运行程序(非服务管理方式)
若无需系统级服务管理(如临时测试),可直接通过命令启动程序并获取PID。
后台启动方式
(1)&
符号:将程序放入后台运行,终端关闭后进程可能终止(需配合nohup
避免):
/usr/local/bin/myapp & # 后台启动,输出默认重定向到终端 echo $! # $!获取最后一个后台进程的PID
(2)nohup
:忽略挂断信号,程序在终端关闭后仍运行,输出默认写入nohup.out
:
nohup /usr/local/bin/myapp & # 后台启动并忽略挂断 echo $! # 获取PID
查看PID
(1)ps
命令:根据进程名或路径查找PID
ps aux | grep myapp # 过滤包含"myapp"的进程(注意grep自身也会显示) ps aux | grep "[m]yapp" # 使用正则避免匹配grep进程 ps -C myapp # 通过进程名查找(需精确) ps -ef | grep /usr/local/bin/myapp # 通过完整路径查找
(2)pgrep
命令:更简洁地根据进程名、用户等查找PID
pgrep myapp # 查找所有名为"myapp"的进程PID pgrep -u myuser myapp # 查找用户"myuser"的"myapp"进程PID pgrep -f "myapp" # 查找命令行包含"myapp"的进程(模糊匹配)
常用命令对比表
场景 | systemd方式 | System V init方式 | 直接运行方式 |
---|---|---|---|
启动服务 | systemctl start 服务名.service |
service 服务名 start |
程序名 & 或nohup 程序名 & |
查看服务状态及PID | systemctl status 服务名 |
service 服务名 status |
ps aux | grep 程序名 |
获取PID(命令行) | systemctl show --property MainPID |
cat /var/run/服务名.pid |
echo $! 或pgrep 程序名 |
开机自启 | systemctl enable 服务名.service |
chkconfig 服务名 on |
需手动配置(如crontab) |
相关问答FAQs
问题1:为什么systemctl status
显示服务运行,但用ps aux | grep
却找不到对应的进程?
解答:可能的原因包括:
- 服务配置为
Type=forking
(旧式服务),主进程会退出,子进程作为实际服务运行,此时MainPID
为子进程PID,但进程名可能与服务名不同; - 服务未正确生成PID文件(如
PIDFile
路径错误或程序未写入PID); - 进程已被终止但systemd未更新状态(可通过
systemctl reset-failed 服务名
重置)。
建议使用systemctl show --property MainPID
确认PID,或检查journalctl -u 服务名
查看日志。
问题2:如何让服务启动后自动将PID记录到指定文件,方便其他程序调用?
解答:在systemd服务文件的[Service]
段中添加PIDFile
字段,并确保程序启动后能生成该文件。
[Service] ExecStart=/path/to/program --daemon PIDFile=/var/run/program.pid
若程序本身不生成PID文件,可在ExecStart
后通过命令写入,
ExecStart=/bin/sh -c '/path/to/program & echo $! > /var/run/program.pid'
配置完成后,执行systemctl daemon-reload && systemctl restart 服务名
,即可通过cat /var/run/program.pid
获取PID。
原创文章,发布者:酷番叔,转转请注明出处:https://cloud.kd.cn/ask/28494.html