7

我收到了一个由几十个(可能超过 100 个,我没有计算过)bash 脚本组成的项目。大多数脚本至少调用另一个脚本。我想得到一个调用图的等价物,其中节点是脚本而不是函数。

有没有现有的软件可以做到这一点?

如果没有,是否有人对如何做到这一点有聪明的想法?

我能想出的最佳计划是枚举脚本并检查基本名称是否唯一(它们跨越多个目录)。如果有重复的基本名称,那就哭吧,因为脚本路径通常保存在变量名中,因此您可能无法消除歧义。如果它们是唯一的,则 grep 脚本中的名称并使用这些结果来构建图表。使用一些工具(建议?)来可视化图表。

建议?

4

3 回答 3

3

通过您的实现包装外壳本身,记录谁调用您包装器并执行原始外壳。

是的,您必须启动脚本才能确定真正使用的脚本。否则,您需要一个与 shell 引擎本身具有相同知识的工具来支持整个变量扩展、PATH 等——我从未听说过这样的工具。

为了可视化调用图,请使用GraphViz的点格式。

于 2011-02-24T20:16:00.263 回答
2

这就是我最终这样做的方式(免责声明:很多都是hack-ish,所以如果你要长期使用它,你可能需要清理一下)......

假设: - 当前目录包含所有有问题的脚本/二进制文件。- 用于构建图形的文件位于 subdir call_graph 中。

创建脚本 call_graph/make_tgf.sh:

#!/bin/bash
# Run from dir with scripts and subdir call_graph
# Parameters:
# $1 = sources (default is call_graph/sources.txt)
# $2 = targets (default is call_graph/targets.txt)

SOURCES=$1
if [ "$SOURCES" == "" ]; then SOURCES=call_graph/sources.txt; fi
TARGETS=$2
if [ "$TARGETS" == "" ]; then TARGETS=call_graph/targets.txt; fi

if [ ! -d call_graph ]; then echo "Run from parent dir of call_graph" >&2; exit 1; fi
(
#  cat call_graph/targets.txt
  for file in `cat $SOURCES `
  do
    for target in `grep -v -E '^ *#' $file | grep -o -F -w -f $TARGETS | grep -v -w $file | sort | uniq`
    do echo $file $target
    done
  done
)

然后,我运行了以下命令(我最终做了仅脚本版本):

cat /dev/null | tee call_graph/sources.txt > call_graph/targets.txt
for file in *
do
  if [ -d "$file" ]; then continue; fi
  echo $file >> call_graph/targets.txt
  if file $file | grep text >/dev/null; then echo $file >> call_graph/sources.txt; fi
done

# For scripts only:
bash call_graph/make_tgf.sh call_graph/sources.txt call_graph/sources.txt > call_graph/scripts.tgf

# For scripts + binaries (binaries will be leaf nodes):
bash call_graph/make_tgf.sh > call_graph/scripts_and_bin.tgf

然后我在yEd中打开生成的 tgf 文件,并让 yEd 进行布局(布局 -> 分层)。我保存为 graphml 以将手动可编辑的文件与自动生成的文件分开。

我发现有些节点在图中没有帮助,例如到处调用的实用程序脚本/二进制文件。所以,我从源/目标文件中删除了这些,并根据需要重新生成,直到我喜欢节点集。

希望这可以帮助某人...

于 2015-04-29T18:17:56.687 回答
0

在每个 shell 脚本的开头,#! 之后插入一行 行,它记录时间戳、脚本的完整路径名和参数列表。

随着时间的推移,您可以挖掘此日志以识别可能的候选者,即非常接近记录的两行代码很可能第一个脚本调用第二个脚本。

这也使您可以专注于仍在实际使用的脚本。

您可以使用 ed 脚本

1a
log blah blah blah
.
wq

并像这样运行它:

find / -perm +x -exec ed {} <edscript

确保使用 -print 而不是 exec 子句测试 find 命令。并且 / 可能不是您想要使用的路径。如果您必须包含 bin 目录,那么您可能需要切换到 grep 以识别要包含的路径名,然后当您有一个包含正确名称的文件时,使用 xargs 而不是 find 来运行脚本。

于 2011-02-25T04:37:32.247 回答