Примерно так я решил ту же проблему в среде, где parallel
не было доступно. Это зависит от функций bash, поэтому вам нужно #!/bin/bash
или явно выполнить скрипт через bash.
MAX_CONCURRENT=50
n=0
some_command_that_outputs_urls \
| while read url
do
{
do_something_with $url
} &
PIDS="$PIDS $!"
((++n))
if test "$n" -ge "$MAX_CONCURRENT"
then
n=0
wait $PIDS
PIDS=""
fi
done
test -n "$PIDS" && wait $PIDS
Можно настроить $MAX_CONCURRENT
, чтобы указать желаемое (приблизительное )максимальное количество потоков. И, конечно же, вы замените some_command_that_outputs_urls
и do_something_with $url
тем, что подходит для вашего сценария. Например, вы можете заменить строку some_command_that_outputs_urls \
на
for i in {0800..9999}; do
for j in {001..032}; do
printf 'http://example.com/%s-%s.jpg\n' $i $j
done
done \
#...| while read url...
и do_something_with $url
просто с
wget $url
окончательный результат
MAX_CONCURRENT=50
n=0
for i in {0800..9999}; do
for j in {001..032}; do
printf 'http://example.com/%s-%s.jpg\n' $i $j
done
done \
| while read url
do
{
wget $url
} &
PIDS="$PIDS $!"
((++n))
if test "$n" -ge "$MAX_CONCURRENT"
then
n=0
wait $PIDS
PIDS=""
fi
done
test -n "$PIDS" && wait $PIDS
Это работает следующим образом: команда генерирует список (в данном случае )URL-адресов на своем стандартном выходе и считывает эту строку за раз в цикл while
(watch для новых строк! ). Он будет порождать до $MAX_CONCURRENT
одновременных процессов, используя $n
для отслеживания количества порожденных процессов и $PIDS
для записи их идентификаторов процессов. После того, как $MAX_CONCURRENT
процессы были порождены (, обратите внимание, что то, что действительно порождается, является составным оператором, поэтому вы можете иметь несколько команд и даже блоков внутри него ), это будет wait
на порожденных PID (это немедленно возвращается, если ни один из указанных PID все еще не выполняется )и сбрасывает свое внутреннее состояние, затем переходит к другому запуску.
Есть несколько способов улучшить этот сценарий, включая улучшенную обработку повторно используемых PID, но он выполняет работу, которую я хотел, в среде, в которой он должен работать, поэтому он достаточно хорош для меня. В моей текущей версии также есть тайм-аут, и он регулярно -выполняется через cron, поэтому риск неконтролируемого времени выполнения намного меньше по сравнению с этой более простой версией.
Я загрузил и вручную извлек пакет драйвера openprinting-lm1100_1.0.2a-6lsb3.2_amd64.deb
.
mkdir /tmp/workdir
cd /tmp/workdir
wget https://www.openprinting.org/download/printdriver/debian/dists/lsb3.2/contrib/binary-amd64/openprinting-lm1100_1.0.2a-6lsb3.2_amd64.deb
ar x openprinting-lm1100_1.0.2a-6lsb3.2_amd64.deb
tar xvf data.tar.gz
[... results at /tmp/workdir/opt/OpenPrinting-lm1100...]
Он содержит ряд файлов, которые можно установить в каталог /opt/OpenPrinting-lm1100/
.
Файлы PPD в каталоге /opt/OpenPrinting-lm1100/ppds/Lexmark/
кажутся полностью идентичными, за исключением названий моделей принтеров. Таким образом, Lexmark 1000, 1020 и 1100 будут обрабатываться этим драйвером совершенно одинаково.
Если различные принтеры в серии настолько неразличимы,возможно, что строка идентификации, полученная CUPS, идентифицирует только серию модели, а не фактическую модель. Это может объяснить строку usb://Lexmark/1000
, которую вы видите.
Я заметил, что файлы PPD содержат различные строки, которые кажутся заключенными ровно в 71 символ, причем &&
указывает перенос, например:
*FoomaticRIPCommandLine: "gs -q -sDEVICE=ppmraw -r300 %A -dBATCH -dNOP&&
AUSE -dPARANOIDSAFER %Z -sOutputFile=- - | /opt/OpenPrinting-lm1100/bin/lm1100 %B -"
По-видимому, это правильный синтаксис строки -для PPD. Живи и учись...
Вышеупомянутая командная строка -в основном использует gs
(, т.е. GhostScript ), для преобразования любого задания печати в формате PDF или PS -в формат ppmraw
, а затем передает результат команде /opt/OpenPrinting-lm1100/bin/lm1100
. который является бинарным. Он должен выводить данные задания на печать в формате, подходящем для принтера, который затем CUPS должен направить на фактическое устройство принтера, что будет примерно как /dev/usb/lp1
при использовании USB -> параллельного преобразователя.
В /opt/OpenPrinting-lm1100/bin/
также есть два простых служебных сценария, названных lm1100change
и lm1100back
. Они жестко закодированы для использования /dev/lp0
и, вероятно, их следует отредактировать, чтобы использовать/dev/usb/lp1
(или что-то еще, что ваш USB -> параллельный адаптер вместо этого становится ). Файл /opt/OpenPrinting-lm1100/doc/README.maintenance
указывает, что lm1100change
должен перемещать печатающую головку в соответствующее положение для замены картриджей, а lm1100back
должен возвращать ее в обычное парковочное положение.
Тот факт, что иногда устройство указано как «Неизвестное», а иногда как «Lexmark 1000», указывает на то, что адаптер USB -> параллельного порта считывает строки идентификации принтера параллельного порта IEEE -1284, поэтому CUPS может их сопоставить. против файлов PPD и таким образом автоматически найти правильный PPD. Файл Lexmark-1100-lm1100-en.ppd
содержит строку:
*1284DeviceID: "DRV:Dlm1100,R1,M0,TF;"
Возможно, вы сможете увидеть строки идентификации с помощью cat /sys/class/usbmisc/lp1/ieee1284_id
:, если оно не пусто, адаптер проверил строку идентификации и получил ответ от принтера.
Ваше сообщение в журнале
configure-printer@usb-003-006.service: Job configure-printer@usb-003-006.service/start failed with result 'dependency'.
указывает, что что-то создало службу systemd
configure-printer@usb-003-006.service
и произошел сбой с ошибкой зависимости. Но, похоже, это всего лишь сценарий на основе udev -, который автоматически -создает очередь печати CUPS для устройства, по сути повторяя то, что вы уже сделали вручную, поэтому здесь это не кажется важным... если только скрипт на основе udev -каким-то образом мешает созданию устройства /dev/usb/lp*
для адаптера.
Существует также устройство /dev/bus/usb/*/*
, соответствующее USB ->параллельному адаптеру, но это универсальный интерфейс USB для libusb
и других USB-драйверов пользовательского пространства. Он использует другой API и бесполезен для приложений, которым требуется интерфейс, похожий на традиционный параллельный порт, например драйвер Lexmark. Если узел устройства /dev/usb/lp*
отсутствует или создается непоследовательно, это может объяснить проблемы, с которыми сталкивается CUPS.