我有一个foo
想从终端运行的进程。同时,我有兴趣确定该进程消耗了多少CPU,因此我想进入top
,找到该进程foo
(只有一个进程具有此名称),从%CPU
列,并将该值附加到文件中,并将日期时间时间戳和提取的值放在一行上。有了这些值,我可以生成一个图和一些描述性统计数据,以更好地了解工作量foo
。
此外,我希望这种 CPU 负载提取能够每秒继续一次n
(例如每秒n=1
),并且我希望它在foo
开始时启动并在foo
完成处理时结束。
据我了解,这需要两个过程同时进行。
关于如何实现这一目标有什么想法吗?最好作为直接命令向终端提供 shell 脚本,作为最后的手段(如有必要)。
编辑:下面评论中的链接回答了如何从 中检索值top
。然而,我仍然需要确定如何模拟运行两个进程——一个“主”进程和一个跟踪进程,跟踪进程分别在主进程开始和结束时开始和结束。
答案1
因为主要部分是通过链接在评论中回答的问题
我将尝试回答你问题的其余部分。
由于我不知道您如何运行“主”进程,因此我将在包装器脚本上下文和 systemd 上下文中介绍这一点
但在此之前我想澄清一个误解:
您无法真正运行这些进程同时地,您应该等待主进程启动(如果您之前启动观察程序)或之后启动观察程序,这将允许观察程序假设主进程已经在运行。
系统:
如果您的进程由 systemd 管理,您很可能拥有该单元的服务文件。
这些文件通常存储在您的发行版中/etc/systemd/system/
或/usr/lib/systemd/system/
取决于您的发行版。
操作这些文件的最简单方法是使用以下语法
systemctl edit <service name> --full
指定--full
将允许您修改原始文件的副本;而不是进行直接编辑(本质上是盲目编辑),如果您不熟悉此特定服务,这会很有用。
您需要进行的实际修改是添加一个ExecStartPre=
orExecStartPost=
和一个ExecStopPost=
ExecStartPre
将执行指定的操作(运行您的观察者脚本/程序)前服务已启动
ExecStartPost
将执行指定的操作(运行您的观察者脚本/程序)后服务已启动仅当启动成功时
同样,ExecStopPost
将执行其指定的操作后服务已退出(已完成 中定义的操作ExecStop
)。
下面是一个例子:
[Unit]
Description=Foo
[Service]
# Start the watcher
ExecStartPre=/usr/bin/foo-watcher
# Actual service start
ExecStart=/usr/sbin/foo-daemon start
# Actual service stop
ExecStop=/usr/sbin/foo-daemon stop
# Stop the watcher
ExecStopPost=/usr/bin/pkill foo-watcher
[Install]
WantedBy=multi-user.target
因为您ExecStopPost
可能更建议通过 PID 而不是名称来终止进程,但是有很多产品示例不这样做;因此,请注意无意中终止同名进程的风险。
启动脚本方法:
基本上,您需要将进程包装在启动 bash 脚本中,因为您想使用此脚本管理多个进程,所以将观察程序和主进程置于后台会很有用。
如果您打算使其成为功能齐全的管理脚本,您还需要跟踪这些后台进程的 pid。
这是一个简单的例子:
#!/bin/bash
# Do we have too many arguments(Or too few)? Exit if so.
if [ $# -ne 1 ]
then
exit 1
fi
if [ "$1" == "start" ]
then
# Start the watcher as a job and save the pid to a variable
/usr/bin/foo-watcher &
wPid="$!"
# Start the main process as a job and save the pid to a variable
/usr/bin/foo-daemon &
mPid="$!"
# Save the PIDs to a file, make sure than the main process
# (foo-daemon) doesn't already do this for us
/usr/bin/echo "$wPid" > /var/run/foo-watcher.pid
/usr/bin/echo "$mPid" > /var/run/foo-daemon.pid
elif [ "$1" == "stop" ]
then
# Grab PID from files and store in a variable, since kill
# doesn't read from stdin
wPid="$(/usr/bin/cat /var/run/foo-watcher.pid)"
mPid="$(/usr/bin/cat /var/run/foo-daemon.pid)"
# Kill the processes
/usr/bin/kill "$wPid"
/usr/bin/kill "$mPid"
# Delete pid files
/usr/bin/rm -f /var/run/foo-watcher.pid
/usr/bin/rm -f /var/run/foo-daemon.pid
else
# We didn't get a valid input, exit (maybe display help?)
exit 1
fi
如果您无法控制主进程的退出(在dd
或rm
或类似进程执行某件事并退出的情况下)。以下是对上述脚本的修改,用于处理这种情况。
#!/bin/bash
# Start the watcher as a job and save the pid to a variable
/usr/bin/foo-watcher &
wPid="$!"
# Start the main process as a job and save the pid to a variable
/usr/bin/foo-daemon &
mPid="$!"
while true
do
#Check ps for the process via PID
status="$(ps -q "$mPid" | wc -l)"
#Did ps return anything, if not, kill the watcher
if [ "$status" -eq 1 ]
then
kill "$wPid"
exit 0
fi
#Interval to check if process is running in seconds
sleep 1
done