Wordpress 更优雅的解决方案;至于;环
这是我的麻烦 让我描述一下情况:我在大量服务器上工作,其中包含大量客户;他们都有一个网络空间,但只有一些人在使用Wordpress 出于安全原因,我希望获得特定服务器的所有Wordpress安装的Wordpress版本(在找到解决方案后,我会将该过程应用于其他服务器) 我发现文件/wp includes/version.php包含行“$wp_version='x.x.x'”——似乎非常适合监视客户的安装情况,并在他们的版本有危险时通知他们 我开始编写命令行,然后将其放入cron中,每月检索一次结果:Wordpress 更优雅的解决方案;至于;环,wordpress,bash,awk,sed,Wordpress,Bash,Awk,Sed,这是我的麻烦 让我描述一下情况:我在大量服务器上工作,其中包含大量客户;他们都有一个网络空间,但只有一些人在使用Wordpress 出于安全原因,我希望获得特定服务器的所有Wordpress安装的Wordpress版本(在找到解决方案后,我会将该过程应用于其他服务器) 我发现文件/wp includes/version.php包含行“$wp_version='x.x.x'”——似乎非常适合监视客户的安装情况,并在他们的版本有危险时通知他们 我开始编写命令行,然后将其放入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
...
获取版本
$ 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=$(awk-F'domains/'{split($2,tmp,/\/);print tmp[1]}'您可以大大简化您的逻辑,使其更高效、更可读:
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 \;)
config\u re='/wp\u includes/version.php$'
而IFS=:read-r文件匹配;do
[[$file=~$config_re]]| |继续#如果是其他版本,则跳过。php
#从文件变量中提取域的逻辑
IFS=/read-ra domain_arr我不知道你想用更优雅,这是一个相当主观的标准,但这里有一些关于更有效地使用某些命令的提示:
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
-exec
的{}
参数被替换为找到的文件的路径。请注意,-exec
命令必须以分号终止,分号必须转义(\;
),以防止shell对其进行解释。find
还可以组合多个分组(\(…\)
)测试动作表达式(-o
,-a
):
grep
如果它是最新的GNUgrep
版本,也比您使用的版本更强大。它部分支持perl
正则表达式(-p
选项),并且只能输出匹配的部分(-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
更新的版本。循环和一点bash黑魔法可能更简单,更易于理解和维护,并且易于通过版本过滤进行扩展:
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 )
re1=“*/domains/*/wp includes/version.php”
re2=“\\$wp\U版本\s*=\s*'\K\d+(\.\d+)”
读取时-d$'\0'f;do
[[$f=~.*/domains/([^/]+)/.*]]和&domain=“${BASH\u重新匹配[1]}”
版本=$(grep-Po“$re2”“$f”)
[[!$version=~4\.8(\.\d+*]]&&printf“%s:%s\n”“$domain”“$version”
完成<欢迎使用stack overflow,您能更清楚地发布文件的示例输入吗?谢谢您的回答!更新了version.php文件的示例。您好;看起来明显比我的管道系统好,我记笔记。谢谢!对于域<代码>域=$(awk-F'domains/'{split($2,tmp,/\/);打印tmp[1]}“我对这篇文章没什么意见,我通常在find上使用-exec来执行操作;但在这个主题上它看起来很糟糕。除非我做得不对。我只是编辑了这个问题,添加了我写的第二个版本。没有真正的需要逐个读取文件。所有匹配项都可以通过一次读取来读取,这将使解决方案更加复杂。”h效率更高。感谢您的回答:我没有足够的开发经验来真正理解这种语法;我曾经使用非常线性的命令行。我们将在这个示例中进行练习。find
命令基本上会生成逗号分隔的输出(/path/to/domain/file:$wp\u version…)读循环将它们读入两个变量file
和match
,IFS设置为:
,这是输入分隔符。在循环中,我们从文件的完整路径提取域,并从匹配中提取版本。仅此而已。您可以参考本文了解read
在Bash:@codeforester I中的工作原理阅读你的答案,很好,但它所做的是查找所有文件,而不仅仅是version.php
,这可能会使速度变慢。这是一个疏忽@3161993。修改了答案。增加了额外的安全性确保我们只查看wp\u includes/versions.php
。通过“更优雅”,我说的是更好地使用一些命令,这些命令将产生与长命令相同的结果。感谢您的解释和示例;我将在工作中尝试并可能实现它。看起来很棒,而且更优化。
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 \;)
$ 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
$ 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
$ re3="\\\$wp_version\s*=\s*'\K\d+(\.\d+)*"
$ grep -Po "$re3" version.php
1.1
$ 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
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 )