这是我的麻烦。
让我来描述一下情况:我在大量服务器上工作,这些服务器包含大量客户;所有这些都有一个网站空间,但只有部分人使用Wordpress。
出于安全考虑,我想获得特定服务器的所有Wordpress安装的Wordpress版本(我会在找到解决方案后将该过程应用于其他人)。
我发现文件/wp-includes/version.php包含“$ wp_version ='xxx'”这一行 - 似乎非常适合关注客户的安装并在版本危险时通知他们。
我开始写一个命令行,然后我会把它放入一个cron来检索结果,每月一次:
for files in $(find /home -type f -iwholename "*/wp-includes/version.php") ; do domain=$(echo $files | awk -F'domains/' '{print $2}' | awk -F'/' '{print $1}') ; version=$(grep "wp_version = " $files | awk -F'=' '{print $2}') ; echo "$domain : $version" ; done | grep -v "4.8" | sed -e "s/'/ /g" -e "s/;/ /g"
上面这一行产生了这种结果:
domain.com : 4.1.3
another.com : 4.7.6
again.com : 4.7.6
看起来我得到了我想要的结果 - 但是,正如你所看到的,这个命令行真的很长,即使我尝试了不同的版本,我也没有找到一个优雅的变体。
当然,我尝试了不同的版本,直到这个结果,这是唯一一个正常工作的版本;我找不到类似的东西,但更好。我认为,真正的问题与结果中的变量定义有关;我正在学习awk但它有点像丑陋,即使它是一个很棒的工具。最后的sed命令清除原始结果,如下所示:
domain.com : '4.1.3';
another.com : '4.7.6';
again.com : '4.7.6';
wp-includes / version.php看起来与它类似:
<?php
/**
* The WordPress version string
*
* @global string $wp_version
*/
$wp_version = '3.9'; # for example
...
如果您看到任何“优化”,请告诉我?这更多是关于教育而不是真正的麻烦。
编辑:目前最优化的版本是我认为的以下版本(足够清晰,易于修改,结果清晰,功能难以理解):
for f in $(find /home -iwholename "*/wp-includes/version.php") ; do d=$(echo $f | awk -F'domains/' '{print $2}' | cut -d"/" -f1) ; v=$(grep '$wp_version = ' $f | sed -e 's/$wp_version = //g' -e "s/'//g" -e 's/;//g') ; echo "$v - $d" ; done
答案 0 :(得分:1)
version=$( awk -F"[\"']" '/^\$wp_version/{print $2}' "$files" )
获取版本
$ cat version.php
<?php
/**
* The WordPress version string
*
* @global string $wp_version
*/
$wp_version = '3.9'; # for example
...
# used field separator either single quote or double quote
$ awk -F"[\"']" '/^\$wp_version/{print $2}' version.php
3.9
对于域名,您可以从
更改domain=$(echo $files | awk -F'domains/' '{print $2}' | awk -F'/' '{print $1}') ;
要
domain=$(awk -F'domains/' '{split($2,tmp,/\//); print tmp[1]}' <<<"$files")
假设你有一个类似
的路径$ files="path/to/domains/domain.com/wordpress/wp-includes/version.php"
$ awk -F'domains/' '{split($2,tmp,/\//); print tmp[1]}' <<<"$files"
domain.com
答案 1 :(得分:0)
您可以大大简化逻辑并使其更加高效和可读:
config_re='/wp_includes/version.php$'
while IFS=: read -r file match; do
[[ $file =~ $config_re ]] || continue # skip if it is some other version.php
# logic to extract the domain from file variable
IFS=/ read -ra domain_arr <<< "$file"
domain="${domain[2]}" # adjust the array index as needed
# logic to extract version from matched part
IFS='=' read -ra version_arr <<< "$match"
version="${version_arr[1]}"
done < <(find /path/to/domains -type f -name version.php -exec grep '$wp_version' {} /dev/null \;)
find /path/to/domains -type f -name version.php -exec grep -H '$wp_version' {} \;
一次性提取所有比赛; grep -H
确保版本文件的完整路径(注意find
目录参数中的完整路径以输出中的匹配为前缀我还没有测试过这段代码。如果您遇到任何问题,我愿意修复它。
答案 2 :(得分:0)
我不知道你想要什么更优雅,这是一个相当主观的标准,但这里有一些关于更有效地使用某些命令的提示:
~/
比您使用的功能更强大。它可以使用正则表达式(find
)进行搜索,对找到的文件执行命令(-regex
动作)...示例:
-exec
$ re1=".*/domains/[^/]*"
$ find /home -type d -regex "$re1" -printf "%f : \n"
domain.com :
another.com :
again.com :
$ re2="*/domains/*/wp-includes/version.php"
$ re3="wp_version"
$ find /home -type f -ipath "$re2" -exec grep "$re3" '{}' \;
$wp_version = '1.1'; # for example
$wp_version = '2.2'; # for example
$wp_version = '3.3'; # for example
的{{1}}参数替换了找到的文件的路径。请注意,{}
命令必须以分号结束,该分号必须进行转义(-exec
)以防止shell对其进行解释。 -exec
还可以合并多个分组(\;
)测试操作表达式(find
,\(...\)
):
-o
-a
如果它是最近的GNU $ find /home \( -type d -regex "$re1" -printf "%f : " \) -o \
\( -type f -ipath "$re2" -exec grep "wp_version" '{}' \; \)
domain.com : $wp_version = '1.1'; # for example
another.com : $wp_version = '2.2'; # for example
again.com : $wp_version = '3.3'; # for example
版本,则比您使用的版本更强大。它部分支持grep
正则表达式(grep
选项)并且只能输出匹配的部分(perl
)。例如:
-P
如果我们将所有这些粘合在一起,并使用bash变量以获得更好的可读性(臭名昭着的作弊以缩短最终的命令行),我们可以使用以下内容:
-o
但这一切都非常复杂。此外,它仅适用于每个域只有一个版本文件,并且不会过滤掉比$ re3="\\\$wp_version\s*=\s*'\K\d+(\.\d+)*"
$ grep -Po "$re3" version.php
1.1
更新的版本。一个循环和一些bash黑魔法可能更简单,更容易理解和维护,并且易于使用版本过滤扩展:
$ re1=".*/domains/[^/]*"
$ re2="*/domains/*/wp-includes/version.php"
$ re3="\\\$wp_version\s*=\s*'\K\d+(\.\d+)*"
$ find /home \( -type d -regex "$re1" -printf "%f : " \) -o \
\( -type f -ipath "$re2" -exec grep -Po "$re3" '{}' \; \)
domain.com : 1.1
another.com : 2.2
again.com : 3.3
请注意在4.8
(re1="*/domains/*/wp-includes/version.php"
re2="\\\$wp_version\s*=\s*'\K\d+(\.\d+)*"
while read -d $'\0' f; do
[[ $f =~ .*/domains/([^/]+)/.* ]] && domain="${BASH_REMATCH[1]}"
version=$( grep -Po "$re2" "$f" )
[[ ! $version =~ 4\.8(\.\d+)* ]] && printf "%s : %s\n" "$domain" "$version"
done < <( find . -type f -ipath "$re1" -print0 )
)和\0
(read
)命令中使用-d $'\0'
分隔符(而不是新行)。如果你有奇怪的目录名,这可能会有所帮助。