xargs에 대한 불규칙한 인수 개수

xargs에 대한 불규칙한 인수 개수

숫자가 왜 이렇게 불규칙합니까?

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-limitsGNU 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은 항상 적합합니다.

관련 정보