숫자가 왜 이렇게 불규칙합니까?
echo {1..200000} | xargs perl -E 'say "ok:", scalar @ARGV'
ok:23691
ok:21840
ok:21840
ok:21840
ok:20261
ok:18720
ok:18720
ok:18720
ok:18720
ok:15648
표준 인수 길이가 더 문명화되었습니다.
perl -E' say "1 " x 900000' | xargs perl -E 'say "ok:", scalar @ARGV'
ok:65520
ok:65520
ok:65520
ok:65520
ok:65520
ok:65520
ok:65520
ok:65520
ok:65520
ok:65520
ok:65520
ok:65520
ok:65520
ok:48240
핵심 요소는 정확히 무엇입니까?
답변1
중요한 숫자는 (모든) 인수의 총 길이이며 명령 버퍼 크기 xargs가 사용하기로 결정합니다.
첫 번째는 실행하는 명령의 고정 명령줄에 따라 달라지며 각 호출에 xargs 인수가 제공됩니다. perl -E 'say "ok:", scalar @ARGV'
는 32바이트이며 문자열을 종료하는 NUL 바이트를 계산합니다(예 perl<NUL>-E<NUL>say "ok:", scalar @ARGV<NUL>
: 두 번째 예에서 모든 인수는 각각 2바이트입니다. 즉 1<NUL>
, .so 32 + 65520 * 2바이트 또는 131072 B = 128 * 1024 B = 128kB입니다.
분명히 첫 번째 예에서는 인수의 길이가 다르고 제공된 개수도 다르지만 논리는 동일해야 합니다. 예를 들어 두 번째부터 네 번째 실행까지의 인수 21840개는 5비트 인수(인수당 6바이트)와 일치합니다(21840 * 6 + 32 = 131072).
명령 버퍼의 크기는 구현에 따라 다를 수 있지만 GNU xargs를 사용하여 이를 표시할 수 xargs --show-limits
있으며 내 Linux에서는 다음을 얻습니다.
$ echo | xargs --show-limits
Your environment variables take up 2305 bytes
POSIX upper limit on argument length (this system): 2092799
POSIX smallest allowable upper limit on argument length (all systems): 4096
Maximum length of command we could actually use: 2090494
Size of command buffer we are actually using: 131072
Maximum parallelism (--max-procs must be no greater): 2147483647
두 번째에서 마지막 행을 보면 정확히 같은 숫자입니다.
-s
예를 들어 10kB 버퍼만 사용하여 사용하는 버퍼 크기를 변경할 수 있습니다 .
$ perl -E' say "1 " x 90000' | xargs -s 10240 perl -E 'say "ok:", scalar @ARGV'
ok:5104
ok:5104
ok:5104
...
물론 -n
개별 매개변수의 수도 제한해야 합니다.
$ echo {1..200000} | xargs -n 10000 perl -E 'say "ok:", scalar @ARGV'
ok:10000
ok:10000
ok:10000
...
--show-limits
환경 변수가 언급되는 이유는 명령줄 매개변수와 동일한 공간을 사용하기 때문이며 버퍼 크기를 시스템 최대값에 가깝게 늘리면 해당 크기도 중요해지기 시작합니다.
시스템에서 계산도 하는지 잘 모르겠습니다.바늘인수 문자열 제한에 대한 반대 의견이 있지만 적어도 xargs는 이에 대해 신경 쓰지 않는 것 같습니다.
답변2
백그라운드 컨텍스트의 경우: Linux 및 기타 Unices에는 명령에 전달할 수 있는 최대 인수 수와 경우에 따라 결과 명령줄의 총 길이에 대한 제한이 있습니다. 이를 처리해야 합니다. 그렇지 않으면 xargs
(이 경우와 같이) 많은 수의 인수가 포함된 명령을 실행할 때 때때로 E2BIG
실패 할 수 있습니다 execvp
.
ARG_MAX
많은 온라인 리소스에서는 이것이 매개변수에 대한 표준 제한이라고 말하지만 이는 잘못된 것입니다. ARG_MAX
이는 단일 매개변수에 대한 것이며 실제로는 그 전에 적용되는 더 많은 제한이 있을 수 있습니다. 이러한 한도는 일반적으로 수량을 기준으로 적용됩니다.바이트수량 대신 결과 명령줄에논쟁(즉, 포인터 배열을 기반으로 함) 이 경우 xargs의 GNU 버전에서는 명령이 구분되는 지점이 bc_args_exceed_testing_limit
사용자 공간에서 고정된 길이( )를 기준으로 결정된다는 사실을 알고 계실 것입니다. xargs --show-limits
GNU xargs를 사용하는 경우 다음 제한 사항 중 일부를 볼 수 있습니다.
% xargs --show-limits </dev/null |& grep -e arg -e command
POSIX upper limit on argument length (this system): 2090868
POSIX smallest allowable upper limit on argument length (all systems): 4096
Maximum length of command we could actually use: 2086632
Size of command buffer we are actually using: 131072
소스 코드에서 이러한 제한을 보려면 하위 항목을 닫은 다음 이전에 매개변수 길이에 대한 테스트를 수행하는 xargs/xargs.c
것을 볼 수 있습니다 .fork()
exec()
[...]
/* If we run out of processes, wait for a child to return and
try again. */
while ((child = fork ()) < 0 && errno == EAGAIN && procs_executing)
wait_for_proc (false, 1u);
switch (child)
{
case -1:
die (EXIT_FAILURE, errno, _("cannot fork"));
case 0: /* Child. */
{
close (fd[0]);
child_error = EXIT_SUCCESS;
prep_child_for_exec ();
if (bc_args_exceed_testing_limit (argv))
errno = E2BIG;
else
execvp (argv[0], argv);
[...]
이 수표는 다음에서 발행되었습니다 lib/buildcmd.c
:
/* Return nonzero if the indicated argument list exceeds a testing limit.
* NOTE: argv could be declared 'const char *const *argv', but it works as
* expected only with C++ compilers <http://c-faq.com/ansi/constmismatch.html>.
*/
bool
bc_args_exceed_testing_limit (char **argv)
{
size_t chars, args;
for (chars=args=0; *argv; ++argv)
{
++args;
chars += strlen(*argv);
}
return (exceeds ("__GNU_FINDUTILS_EXEC_ARG_COUNT_LIMIT", args) ||
exceeds ("__GNU_FINDUTILS_EXEC_ARG_LENGTH_LIMIT", chars));
}
다음 숫자는 문자열 형식에서 더 길기 때문에 더 많은 공간을 차지하므로 xargs가 새 명령을 더 적극적으로 생성하게 됩니다.
답변3
xargs
필요매개변수를 조정하여 크기 설정이는 운영 체제에 의해 제한됩니다. 첫 번째 예의 인수가 커지므로 각 호출에 적합하지 않습니다 perl
. 한도 내에서 5자 인수보다 3자 인수를 더 많이 수용할 수 있습니다.
두 번째는 항상 "1"을 인수로 가지므로 65520은 항상 적합합니다.