谁在吃数据?沙格斯?

dot*_*hen 2 shell bash debugging xargs php

我正在尝试使用内置的 PHP linter 解析 PHP 文件的递归目录,其工作方式如下:

$ php -l good.php
No syntax errors detected in good.php

$ php -l bad.php
PHP Parse error:  syntax error, unexpected ''foo'' (T_CONSTANT_ENCAPSED_STRING), expecting ')' in bad.php on line 3
Errors parsing bad.php
Run Code Online (Sandbox Code Playgroud)

我们可以看到,通过 linting 的文件No syntax errors输出包含Errors parsing.

我看到我在当前目录中递归地有 12147 个 PHP 文件,但是 PHP linter 只输出七行:

$ find . -name \*.php -print0 | xargs -0 ls -l | wc -l
12147

$ find . -name \*.php -print0 | xargs -0 php -l | wc -l
7
Run Code Online (Sandbox Code Playgroud)

由于 PHP 只解析了 7 个文件,我可以使用headwithls查找一些尚未解析的文件:

$ find . -name \*.php -print0 | xargs -0 ls -l | head
-rw-r--r-- 1 dotan dotan      1927 Jan 13 10:13 ./bootstrap/app.php
-rw-r--r-- 1 dotan dotan      1076 Jan 13 10:13 ./bootstrap/autoload.php
-rw-rw-r-- 1 dotan dotan     25620 Mar 12 12:29 ./bootstrap/cache/services.php
-rw-r--r-- 1 dotan dotan      2493 Jan 13 10:13 ./bootstrap/paths.php
-rwxrwxr-x 1 dotan dotan     20008 Mar 12 12:30 ./config/app.php
-rw-r--r-- 1 dotan dotan      3304 Jan 13 10:13 ./config/auth.php
-rw-r--r-- 1 dotan dotan      1819 Jan 13 10:13 ./config/cache.php
-rw-r--r-- 1 dotan dotan      3751 Jan 13 10:13 ./config/cartalyst.sentinel-addons.social.php
-rw-r--r-- 1 dotan dotan      6849 Jan 13 10:13 ./config/cartalyst.sentinel.php
-rw-r--r-- 1 dotan dotan      1020 Jan 13 10:13 ./config/compile.php
xargs: ls: terminated by signal 13

$ find . -name \*.php -print0 | xargs -0 php -l
No syntax errors detected in ./bootstrap/paths.php
No syntax errors detected in ./vendor/watson/validating/src/ValidatingTrait.php
No syntax errors detected in ./vendor/giggsey/libphonenumber-for-php/src/libphonenumber/data/PhoneNumberMetadata_SI.php
No syntax errors detected in ./vendor/php-vcr/php-vcr/src/VCR/Event/BeforePlaybackEvent.php
No syntax errors detected in ./vendor/laravel/framework/src/Illuminate/Support/Facades/Blade.php
No syntax errors detected in ./resources/views/emails/appointment/updated/body.blade.php
No syntax errors detected in ./app/WL/Modules/Location/Commands/RemoveClientLocationCommand.php
Run Code Online (Sandbox Code Playgroud)

然而,当我尝试解析其中一个文件时,我发现它确实产生了预期的输出(解析通过或失败):

$ php -l ./bootstrap/cache/services.php
No syntax errors detected in ./bootstrap/cache/services.php
Run Code Online (Sandbox Code Playgroud)

我已经检查过,无论是通过还是失败的 linting 都不会将预期的行打印到 stderr:

$ php -l good.php | grep rr
No syntax errors detected in good.php

$ php -l bad.php | grep rr
PHP Parse error:  syntax error, unexpected ''foo'' (T_CONSTANT_ENCAPSED_STRING), expecting ')' in bad.php on line 3
Errors parsing bad.php
Run Code Online (Sandbox Code Playgroud)

我现在应该检查什么?我的最终目标是整理所有文件,然后使用 grepError parsing来解决这些问题。

Gil*_*il' 7

要查看 xargs 是否有所不同,请运行它运行的命令行。这里有几种方法可以准确查看它运行的内容,同时又不冒险改变它运行的内容:

  • 编写一个php在临时目录中调用的脚本并将其放在$PATH. 在此脚本中,记录参数(并可选择在php之后运行真实的)。
  • 在日志记录机制下运行整个命令行,例如strace.

你会发现命令是这样的

php -l ./bootstrap/app.php ./bootstrap/autoload.php ./bootstrap/cache/services.php …
Run Code Online (Sandbox Code Playgroud)

下一步是调查此命令的作用。

我不熟悉,php但我猜它只将第一个文件名视为 PHP 脚本名称,而在 lint 模式下它只是忽略所有后续参数。所以你需要php -l为每个脚本运行一次,总共 12147 次,而不是使用xargs的分组行为。

最简单的方法是

find . -name \*.php -exec php -l {} \;
Run Code Online (Sandbox Code Playgroud)

但即使某些调用php返回非零状态,此命令也将始终返回 0 。虽然 find 在 21 世纪大多不需要 xargs,但 xargs 的一个好处是,如果任何命令调用返回非零状态,它会返回非零状态。所以运行 xargs,但用-n选项告诉它一次只处理一个文件。

find . -name \*.php -print0 | xargs -0 -n 1 php -l
Run Code Online (Sandbox Code Playgroud)