我想读取以下命令的输出,并将该行中的某些单词存储到某些变量中:
ps -eaf |grep mongod
输出:
root 12911 1 7 16:59 ? 00:05:48 /home/mongo/bin/mongod -f /etc/mongod.conf --replSet mongoReplica --port 27017 --dbpath /home/mongo/data/db/rs0-1 --oplogSize 700
root 22259 7895 0 18:16 pts/4 00:00:00 grep mongod
这里,";12911";是PID/主页/mongo/"是CMD。我想在这里写一个if条件(或者for循环?(来读取
- 如果存在"--端口27017";在该行中,然后存储其PID,";12911";在变量中
- 并且存储"/home/mongo/bin/mongod-f/etc/mongod.conf--replSet mongoReplica--端口27017--dbpath/home/mongo/data/db/rs0-1--oplogSize 700";在另一个变量中
- 并且存储"/home/mongo/data/db/rs0-1";在另一个变量中
这就是我目前所拥有的:
ps -eaf | grep mongod | while read -r pid cmd; do
echo "pid: $pid, cmd: $cmd"
done
电流输出:
pid: root, cmd: 12911 1 6 16:59 ? 00:05:56 /home/mongo/bin/mongod -f /etc/mongod.conf --replSet mongoReplica --port 27017 --dbpath /home/mongo/data/db/rs0-1 --oplogSize 700
pid: root, cmd: 24862 24860 0 18:29 pts/4 00:00:00 grep mongod
OP意见的假设和收集:
- 可能有多个
mongod
进程(每个OP使用while
循环( - 解析后的数据需要存储在变量中,以便在后续脚本中使用(根据OP的注释(
- OP的
ps
命令允许格式化输出
由于ps
的输出在不同的*nix实现中可能有很大的差异,我将从ps
输出我们需要的内容开始,例如:
ps -eo pid,cmd # list all processes, only display the pid and command
然后,我们可以将其发送到grep
命令,以仅拉出感兴趣的行(即,包含mongod
和--port 27017
:
ps -eo pid,cmd | grep -- '[m]ongod .*--port 27017`
注意:将m
放在括号中应消除grep
命令的ps
输出记录(即不需要运行grep -v grep
跳过grep
行(
为了展示这个答案如何处理多个mongod
进程,我使用了两组ps
输出(格式为-o pid,cmd
(:
12911 /home/mongo/bin/mongod -f /etc/mongod.conf --replSet mongoReplica --port 27017 --dbpath /home/mongo/data/db/rs0-1 --oplogSize 700
23952 /home/mongo/bin/mongod -f /etc/mongod.conf --replSet mongoReplica --port 27017 --dbpath /home/mongo/data/db/rs0-2 --oplogSize 700
为了使解析后的数据能够用于后续处理,我们需要修改while
循环结构,以确保我们不会将解析后数据存储在子流程调用中。这意味着:
# we replace this:
ps ... | grep ... | while read -r ...
# with this:
while read -r ... ; done < <(ps ... | grep ...)
把这一切结合在一起,我们有:
unset pids cmds dbpaths # make sure nothing in our array variables
i=1 # initialize our array index
while read -r pid cmd
do
pids[i]="${pid}" # store current pid
cmds[i]="${cmd}" # store current cmd
dbpath="${cmd##*--dbpath[ =]}"
dbpaths[i]="${dbpath%% *}" # store current dbpath
((i++)) # increment the array index for next pass through the loop
done < <(ps -eo pid,cmd | grep -- '[m]ongod .*--port 27017')
# at this point we've finished parsing the 'ps' output and follow-on
# processing can access this data via the 3x arrays, eg;
for (( i=1 ; i<=${#pids[@]} ; i++ ))
do
echo "++++++++++++++++ dataset # ${i}"
echo "pid: ${pids[i]}"
echo "cmd: ${cmds[i]}"
echo "dbpath: ${dbpaths[i]}"
done
echo "++++++++++++++++"
这将生成:
++++++++++++++++ dataset # 1
pid: 12911
cmd: /home/mongo/bin/mongod -f /etc/mongod.conf --replSet mongoReplica --port 27017 --dbpath /home/mongo/data/db/rs0-1 --oplogSize 700
dbpath: /home/mongo/data/db/rs0-1
++++++++++++++++ dataset # 2
pid: 23952
cmd: /home/mongo/bin/mongod -f /etc/mongod.conf --replSet mongoReplica --port 27017 --dbpath /home/mongo/data/db/rs0-2 --oplogSize 700
dbpath: /home/mongo/data/db/rs0-2
++++++++++++++++
如果您在Linux上,一个更健壮的解决方案是检查/proc
文件系统中的机器可读信息。
#!/bin/bash
for pid in $(pidof mongod); do
cmdline=$(tr -s ' ' ' ' </proc/$pid/cmdline)
if grep -Fe '--port 27017' <<<"$cmdline"; then
dbpath=${cmdline##*--dbpath[ =]}
dbpath=${dbpath%% *}
printf '%sn' 'We can haz successfullitudity!'
"PID: $pid" "DB path: $dbpath" "Full command line: $cmdline"
fi
done
可能存在多个mongod
实例;在这种情况下,你必须分别想办法。
简而言之,pidof cmd
获取运行cmd
的所有进程的PID;然后我们检查关于CCD_ 23中的每个返回的进程ID的信息。例如,进程1234的当前工作目录为/proc/1234/cwd
,用于启动进程的命令行位于/proc/1234/cmdline
。我们将grep
作为--port
选项的命令行,如果成功,我们还将使用简单的链式参数展开来解析--dbpath
。
这不是一个完整的脚本;你必须继续它才能真正对我们定义的变量做一些事情。一旦脚本完成,变量将不再可用。
这仍然有些脆弱;例如,如果mongod
为同一个选项名称提供了多个别名,则必须解析命令行,直到找到所需选项的一个别名为止。