Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/wordpress/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Wordpress 更优雅的解决方案;至于;环_Wordpress_Bash_Awk_Sed - Fatal编程技术网

Wordpress 更优雅的解决方案;至于;环

Wordpress 更优雅的解决方案;至于;环,wordpress,bash,awk,sed,Wordpress,Bash,Awk,Sed,这是我的麻烦 让我描述一下情况:我在大量服务器上工作,其中包含大量客户;他们都有一个网络空间,但只有一些人在使用Wordpress 出于安全原因,我希望获得特定服务器的所有Wordpress安装的Wordpress版本(在找到解决方案后,我会将该过程应用于其他服务器) 我发现文件/wp includes/version.php包含行“$wp_version='x.x.x'”——似乎非常适合监视客户的安装情况,并在他们的版本有危险时通知他们 我开始编写命令行,然后将其放入cron中,每月检索一次结

这是我的麻烦

让我描述一下情况:我在大量服务器上工作,其中包含大量客户;他们都有一个网络空间,但只有一些人在使用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
    如果它是最新的GNU
    grep
    版本,也比您使用的版本更强大。它部分支持
    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 )