如何通过一些预定义变量来捆绑组合命令?

如何通过一些预定义变量来捆绑组合命令?

如果我们直接在桁架参数中使用组合命令,它可以正常工作,没有任何问题。

但是,如果我们在 truss 参数中间接使用组合命令的预定义变量,则会失败。

# 
# truss -adefo /tmp/not_a_term.out  ls -ltr|head
total 233888
drwx------    2 root     system          256 Feb 22 2017  lost+found
-rw-r--r--    1 root     system          406 Feb 22 2017  .sr_migrate.log
-rw-------    1 root     system            0 Feb 22 2017  .strload.mutex
-rw-r--r--    1 root     system          708 Feb 22 2017  ctrmc_MDdr.dbg
-rw-r--r--    1 root     system          708 Feb 22 2017  IBM.CSMAgentRM_dr.sh.dbg
-rw-r--r--    1 root     system         9114 Feb 23 2017  .tzlist
d-w-------    2 root     system          256 Feb 23 2017  saved_errmbatch
d-w-------    2 root     system          256 Feb 23 2017  errmbatch
-rw-r--r--    1 root     system          179 Feb 23 2017  mirror_1.out
#            
# 
# 
# A1="ls -ltr|head"                             
# 
# 
# truss -adefo /tmp/not_a_term.out  $A1         
ls: Not a recognized flag: |
ls: Not a recognized flag: h
Usage: ls [-1ACFHLNRSabcdefgiklmnopqrstuxEUX] [File...]
# 
# 

答案1

你写

如果我们直接在桁架参数中使用组合命令

但这听起来很误导。在命令中:

truss -adefo /tmp/not_a_term.out  ls -ltr|head

shelltruss以四个参数-adefo/tmp/not_a_term.outls和运行-ltr。到那里的管道head不是 参数的一部分truss,而是特殊的 shell 语法,它导致 shellhead与 并发运行truss,并且 的标准输出truss连接到 的标准输入head。除了看到它的输出进入管道之外,truss不知道它head在那里。

在另一个命令中:

truss -adefo /tmp/not_a_term.out  $A1    

没有管道。相反,shelltruss使用参数-adefo以及扩展和分割的/tmp/not_a_term.out任何内容运行。$A1有了,A1="ls -ltr|head"就会产生参数-adefo/tmp/not_a_term.outls。最终启动-ltr|head时,注意到它无法将 识别为选项字符。trusslsls|

如果你想解释shell语法的变量内容,你需要通过运行它eval,例如

A1="ls -ltr|head"
eval "truss -adefo /tmp/not_a_term.out $A1" 

它首先扩展为truss -adefo /tmp/not_a_term.out ls -ltr|head,然后由 shell 解析,类似于上面的第一个命令。

请注意,由于存在额外的解析步骤,因此您需要小心正确地引用任何数据。例如,如果您在变量中保存文件名,则将解析该名称中嵌入的任何 shell 语法。考虑:

file='$(date >&2)'
touch "$file"
# you now have a filename with a literal $ in it
# this runs 'ls' on the file
ls -ld "$file"
# this runs 'date' and 'ls -ld'
eval ls -ld "$file"

根据您的具体需求,您可以创建一个函数来在某些命令上运行 truss 并通过 head 通过管道输出,例如这将运行相同的管道:

trusshead() {
    outfile=$1
    shift
    truss -adefo "$outfile" "$@" | head
}
trusshead /tmp/not_a_term.out ls -ltr

答案2

最后,我们发现类似的需求函数必须通过包含这些多个组合命令的脚本来运行。
注意:truss 命令似乎只能接受一个“外部”命令作为 argv 一次,而不是接受多个“内部”命令作为 argc。

#
# 
# truss -adefo /tmp/not_a_term.out  ls -ltr|head
total 233888
drwx------    2 root     system          256 Feb 22 2017  lost+found
-rw-r--r--    1 root     system          406 Feb 22 2017  .sr_migrate.log
-rw-------    1 root     system            0 Feb 22 2017  .strload.mutex
-rw-r--r--    1 root     system          708 Feb 22 2017  ctrmc_MDdr.dbg
-rw-r--r--    1 root     system          708 Feb 22 2017  IBM.CSMAgentRM_dr.sh.dbg
-rw-r--r--    1 root     system         9114 Feb 23 2017  .tzlist
d-w-------    2 root     system          256 Feb 23 2017  saved_errmbatch
d-w-------    2 root     system          256 Feb 23 2017  errmbatch
-rw-r--r--    1 root     system          179 Feb 23 2017  mirror_1.out
# 
# 
# wc -l /tmp/not_a_term.out
     595 /tmp/not_a_term.out
# 
# 
# grep head /tmp/not_a_term.out
# 
# 
# grep -E "arg|execve"   /tmp/not_a_term.out
25296928: 0.0000:        execve("/usr/bin/ls", 0x2FF22C6C, 0x200132F8)  argc: 2
25296928: 64291025:  argv: ls -ltr 
# 
# 
# 
# echo "ls -ltr|head  >t_2 2>&1" > l_h.sh
# 
# 
# cat l_h.sh
ls -ltr|head  >t_2 2>&1
# 
# 
# chmod 744 l_h.sh
# 
# 
# truss -adefo /tmp/not_a_term.out ./l_h.sh
# 
# 
# grep -E "arg|execve" /tmp/not_a_term.out
28377090: 0.0000:        execve("./l_h.sh", 0x2FF22C70, 0x200132F8) Err#8  ENOEXEC
28377090: 69468411: 0.0138:        execve("/usr/bin/sh", 0xF07F8558, 0x200132F8)  argc: 3
28377090: 69468411:  argv: sh -- ./l_h.sh
25165906:       60555303: 0.0408:        execve("/usr/bin/ls", 0x200117A8, 0x200117D8)  argc: 2
25165906:       60555303:  argv: ls -ltr
25165906:       60555303: 0.0486:        execve("/usr/bin/head", 0x200117A8, 0x200117D8) = 0xD0539130  argc: 1
27131920:       64553157:  argv: head
# 
# 



相关内容