我已经交了一个包含几十个(可能超过100个,我没有计算过)bash脚本的项目。大多数脚本至少调用另一个脚本。我想得到一个调用图的等价物,其中节点是脚本而不是函数。
有没有现成的软件可以做到这一点?
如果没有,是否有人对如何做到这一点有聪明的想法?
我能想到的最佳计划是枚举脚本并检查基本名称是否唯一(它们跨越多个目录)。如果有重复的基本名称,则哭,因为脚本路径通常以变量名称保存,因此您可能无法消除歧义。如果它们是唯一的,那么grep脚本中的名称并使用这些结果来构建图形。使用一些工具(建议?)来可视化图形。
建议?
答案 0 :(得分:3)
通过实现包装shell本身,记录调用包装器的人并执行原始shell。
是的,你必须启动脚本才能识别真正使用的脚本。否则你需要一个与shell引擎本身具有相同知识的工具来支持整个变量扩展,PATH等 - 我从来没有听说过这样的工具。
为了使调用图形可视化,请使用GraphViz的点格式。
答案 1 :(得分:2)
这里是我如何做到这一点(免责声明:很多都是黑客,所以如果你长期使用它,你可能想要清理)......
假设: - 当前目录包含所有相关的脚本/二进制文件。 - 构建图形的文件在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进行布局(Layout - > Hierarchical)。我保存为graphml,将手动编辑的文件与自动生成的文件分开。
我发现某些节点在图表中没有帮助,例如在整个地方调用的实用程序脚本/二进制文件。因此,我从sources / targets文件中删除了这些文件,并根据需要重新生成,直到我喜欢节点集。
希望这有助于某人...
答案 2 :(得分:0)
在每个shell脚本的开头插入一行,#! line,记录时间戳,脚本的完整路径名和参数列表。
随着时间的推移,你可以挖掘这个日志以识别可能的候选者,即非常靠近的两行记录第一个脚本调用第二个脚本的可能性很高。
这也使您可以专注于仍在使用的脚本。
您可以使用ed脚本
1a
log blah blah blah
.
wq
然后像这样运行:
find / -perm +x -exec ed {} <edscript
确保使用-print而不是exec子句测试find命令。和/可能不是您想要使用的路径。如果你必须包含bin目录,那么你可能需要切换到grep以识别要包含的路径名,然后当你有一个完整的正确名称的文件时,使用xargs而不是find来运行脚本。