如何从一行中读取某些单词,并将它们存储在bash脚本中的不同变量中



我想读取以下命令的输出,并将该行中的某些单词存储到某些变量中:

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为同一个选项名称提供了多个别名,则必须解析命令行,直到找到所需选项的一个别名为止。

相关内容

  • 没有找到相关文章

最新更新