2015-01-06 1 views
4

Я пытаюсь запустить ряд команд параллельно через xargs. Я создал пустой список разделенных команд в файле cmd_list.txt, а затем попытался запустить их параллельно с 6 нитей следующим образом:Ошибка wget и bash: bash: строка 0: fg: нет управления заданиями

cat cmd_list.txt | xargs -0 -P 6 -I % bash -c % 

Однако, я получаю следующее сообщение об ошибке:

bash: line 0: fg: no job control 

I 'сузилась проблема, связанная с длиной отдельных команд в списке команд. Вот пример искусственно длинную команду для загрузки изображения:

mkdir a-very-long-folder-de090952623b4865c2c34bd6330f8a423ed05ed8de090952623b4865c2c34bd6330f8a423ed05ed8de090952623b4865c2c34bd6330f8a423ed05ed8 
wget --no-check-certificate --no-verbose -O a-very-long-folder-de090952623b4865c2c34bd6330f8a423ed05ed8de090952623b4865c2c34bd6330f8a423ed05ed8de090952623b4865c2c34bd6330f8a423ed05ed8/blah.jpg http://d4u3lqifjlxra.cloudfront.net/uploads/example/file/48/accordion.jpg 

Просто работает в wget команду на себе, без списка файлов и без xargs, работает отлично. Однако выполнение этой команды в командной Баш строке (опять же, без списка файлов) не с no job control error:

echo "wget --no-check-certificate --no-verbose -O a-very-long-folder-de090952623b4865c2c34bd6330f8a423ed05ed8de090952623b4865c2c34bd6330f8a423ed05ed8de090952623b4865c2c34bd6330f8a423ed05ed8/blah.jpg http://d4u3lqifjlxra.cloudfront.net/uploads/example/file/48/accordion.jpg" | xargs -I % bash -c % 

Если я выхожу из длинного имени папки и, следовательно, сократить команду, она отлично работает:

echo "wget --no-check-certificate --no-verbose -O /tmp/blah.jpg http://d4u3lqifjlxra.cloudfront.net/uploads/example/file/48/accordion.jpg" | xargs -I % bash -c % 

xargs имеет параметр -s (размер), который может изменить размер макс длины командной строки, но я пытался увеличить его до абсурдных размеров (например, 16000), без какого-либо эффекта. Я думал, что проблема может быть связана с длиной строки, передаваемой в bash -c, но следующая команда также работает без проблем:

bash -c "wget --no-check-certificate --no-verbose -O a-very-long-folder-de090952623b4865c2c34bd6330f8a423ed05ed8de090952623b4865c2c34bd6330f8a423ed05ed8de090952623b4865c2c34bd6330f8a423ed05ed8/blah.jpg http://d4u3lqifjlxra.cloudfront.net/uploads/example/file/48/accordion.jpg" 

Я понимаю, что есть и другие варианты для запуска команд параллельно, например как parallel (https://stackoverflow.com/a/6497852/1410871), но я все еще очень заинтересован в исправлении моей установки или, по крайней мере, выяснении, где это происходит.

Я нахожусь в Mac OS X 10.10.1 (Yosemite).

+0

Эта точная пара линий не подходит для вас? Он работает здесь, в CentOS. Если это единственная пара строк в файле, она все равно терпит неудачу с xargs? Сбой (когда он сам по себе), если вы запустите 'bash -c '$ (

+0

@EtanReisner, хотя моя цель - использовать список файлов, у меня есть ошибки еще до этого шага. Эта строка не работает: 'echo 'wget --no-check-certificate --no-verbose -O a-very-long-folder-de090952623b4865c2c34bd6330f8a423ed05ed8de090952623b4865c2c34bd6330f8a423ed05ed8de090952623b4865c2c34bd6330f8a423ed05ed8/blah.jpg http://d4u3lqifjlxra.cloudfront.net/uploads/example/file /48/accordion.jpg "| xargs -I% bash -c% ' –

+0

@EtanReisner: Re:« Эта точная пара строк терпит неудачу для вас? [...] Если это единственная пара строк в файле, она все равно терпит неудачу с xargs? »: I подумайте, что у вас есть это в обратном направлении. Кажется, что OP говорит, что он * только * терпит неудачу при запуске через xargs. – ruakh

ответ

2

Похоже, решение, чтобы избежать параметр -I для xargs, который, согласно OS X xargs man page, имеет предел 255 байт на строку замены. Вместо этого доступен параметр -J, который не имеет ограничения на 255 байтов.

Так что моя команда будет выглядеть так:

echo "wget --no-check-certificate --no-verbose -O a-very-long-folder-de090952623b4865c2c34bd6330f8a423ed05ed8de090952623b4865c2c34bd6330f8a423ed05ed8de090952623b4865c2c34bd6330f8a423ed05ed8/blah.jpg http://d4u3lqifjlxra.cloudfront.net/uploads/example/file/48/accordion.jpg" | xargs -J % bash -c % 

Однако в команде выше, только часть замены строки до первого пробела передается колотить, так Баш пытается выполнить:

wget 

который, очевидно, приводит к ошибке. Мое решение для того, чтобы xargs интерпретирует команды утратившим запятыми вместо пробелов, разделенных с помощью параметра -0, например, так:

echo "wget --no-check-certificate --no-verbose -O a-very-long-folder-de090952623b4865c2c34bd6330f8a423ed05ed8de090952623b4865c2c34bd6330f8a423ed05ed8de090952623b4865c2c34bd6330f8a423ed05ed8/blah.jpg http://d4u3lqifjlxra.cloudfront.net/uploads/example/file/48/accordion.jpg" | xargs -0 -J % bash -c % 

и, наконец, это работает!

Спасибо @CharlesDuffy, который предоставил большую часть этого понимания. И я не благодарю мою версию OS X xargs за ее плохое управление строками замены, которые превышают ограничение в 255 байт.

+0

Единственная часть этого ответа, который я не уверен в отношении правильности, - это утверждение, что bash выполнял только 'wget'; из журнала 'set -x', который вы отправили в комментариях, похоже, что bash выполнял'% '(что также объясняет сообщение об ошибке, которое вы получили в результате, поскольку' bash -c '%' 'генерирует сообщенную ошибку, тогда как 'bash -c 'wget'' не делает. –

+0

Извините, я добавил более позднюю команду в https://gist.github.com/drdan14/2d6d32aa11d058e3e443. В результате получилось '+ (0) :: 0: wget'. Поэтому я не думаю, что была проблема, связанная с '%'. –

+0

На самом деле - это похоже на проблему из-за отсутствия аргумента '-0' в' xargs' (и 'echo', а не' printf '% s \ 0''). –

1

Я подозреваю, что это символ процента, и ваша верхняя оболочка жалуется.

cat cmd_list.txt | xargs -0 -P 6 -I % bash -c %

Проценты являются метасимволами для управления заданиями. «fg% 2», например. «kill% 4».

Попробуйте ускользнуть от процентов с обратной косой чертой, чтобы сигнализировать верхней оболочке, что она не должна пытаться интерпретировать проценты, а xargs должен быть передан буквальным процентом.

cat cmd_list.txt | xargs -0 -P 6 -I \% bash -c \%

+1

Я подозреваю, что это _is_ связано с тем, почему указывается конкретная ошибка (ссылка на управление заданиями), но также и то, что предлагаемое исправление не будет работать: журналы, данные из вызова 'bash -x' (связанного в комментарии) показывают, что это оболочка, начатая xargs, дающая ошибку, а не внешнюю оболочку, ответственную за вызов xargs, - и (a) выполняемое здесь экранирование не переносится на внутреннюю оболочку и (b) xargs предположительно, чтобы заменить '%' символом командной строки. –

+0

@ChadMiller. Ваша теория имеет смысл, но избежание «%» не влияет; результаты те же, что и с невыбранным '%'. –