Назад | Перейти на главную страницу

Последовательные команды Bash. Вызов функций без запуска новых потоков

У меня есть следующий сценарий (в конце объяснения и вопроса).

Есть две функции. По первой функции есть вызов расширения firefox -print. Все работает нормально, если я запускаю его построчно.

Проблема в том, что внутри bash-скрипта firefox вызывается много раз за несколько секунд, вместо того, чтобы вызываться один раз и ждать завершения.

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

Есть ли способ заставить bash не запускать потоки? (что, я полагаю, делает)

Спасибо.

Это мой сценарий (это bash, а не sh из-за команды let)

#!/bin/bash

####TODO###
####variables
# join files
# send with attachment

## Date, to be used as reference on tmp files
DATE=`date +%Y%m%d`
## File where all webs to report are listed
WEBSFILE="/home/marc.riera/Desktop/reports/websfile.txt"
## Where to store all the files. 
WORKDIR="/home/marc.riera/Desktop/reports"

##################do not edit under this line
TMPDIR=$WORKDIR/$DATE
test -d $TMPDIR || mkdir -p $TMPDIR && echo "Create folder $TMPDIR for temporal usage"
REPORT=$WORKDIR/Report_$DATE.pdf

##firefox -print "http://fbmsgga01/ganglia/?m=cpu_report&r=month&s=descending&c=CPU+cluster&h=&sh=1&hc=4&z=small" -printmode pdf -printdelay 5 -printfile ~/Desktop/reports/test.pdf
firefoxprint (){
     web2Print=$1
     outputFile=$2
     echo -n "printing $1 on $2"
     firefox -print "$web2Print" -printmode pdf -printdelay 5 -printfile $outputFile
}

##gs -dNOPAUSE -sDEVICE=pdfwrite -sOUTPUTFILE=dospdf.pdf -dBATCH ganglia.pdf test.pdf
pdfjoin (){
     outputFile=$1
     origA=$2
     origB=$3
     echo -n "Joining $origA and $origB into $outputFile"
     gs -dNOPAUSE -sDEVICE=pdfwrite -sOUTPUTFILE=$outputFile -dBATCH $origA $origB
}


###################################### MAIN
#######################################
clear
COUNTER=0
for web in `cat $WEBSFILE|grep -v '^#'`
do
     firefoxprint $web $TMPDIR/$COUNTER.pdf
     let COUNTER+=1
done
echo "--------------------" $COUNTER
while [ $COUNTER -gt 0 ]; do
    let COUNTER=COUNTER-1
    pdfjoin $REPORT $REPORT $TMPDIR/$COUNTER.pdf
done

echo "done"
exit 0

Я не очень хорошо знаком с использованием FireFox для печати, но вы пробовали использовать bash wait команда? Вы можете скормить ему конкретный PID, которого нужно ждать. Итак, следуя одной из команд печати firefox, вы можете просто сделать wait $!. Или, если вы ничего не укажете и просто используйте wait, он просто будет ждать завершения всех дочерних процессов.

Я не могу гарантировать, что FireFox с этим справится. Но попробовать стоит.

Если есть запущенный firefox, вызов firefox просто связывается с ним, передает запрос на печать и немедленно выходит. Запрос на печать выполняется асинхронно в работающем экземпляре. Я не знаю, есть ли способ получить уведомление о завершении печати.

Обходной путь (непроверенный) - создать новый профиль в вашем скрипте (распаковать подготовленный zip под произвольным именем). Вы можете запускать несколько экземпляров firefox, если они используют разные профили. Удалите временный профиль после выхода из Firefox. Это предполагает, что расширение печати не оставляет запущенным экземпляр firefox; если это так, вы можете взломать его, чтобы выйти из firefox после его завершения.

В конце процедуры firefoxprint () добавьте:

  while [ ! -s $outputFile ]; do
    sleep 1
  done

что должно дать вам хотя бы некоторые delay - он ждет, пока не появится выходной файл ненулевой длины, прежде чем продолжить. Надеюсь, это замедлит его настолько, что последующие вызовы будут использовать существующий firefox, а не думать, что они должны создавать свои собственные.

Когда ты звонишь firefox без указания полного каталога, он запустит сценарий оболочки, который выполняет exec фактического исполняемого файла. Это может быть причиной вашей проблемы, или исполняемый файл может выполнять двойную вилку, которая заставляет его работать в фоновом режиме без использования &. Не знаю, как это предотвратить.

Осталось только одно ждать, чтобы это сделать.

а) Создайте специальный профиль в firefox для печати:

firefox -no-remote -ProfileManager

б) Запустите firefox с помощью firefox -no-remote -P

в) ждать

Хорошо, наконец решено. Спасибо за вашу помощь.

Была еще одна проблема: cron запускает firefox без переменных env, поэтому мне пришлось определить отображение, на котором работать.

Вот окончательный код.

#!/bin/bash

#autor : Joan Marc Riera Duocastella. 
#license : BSD i guess. I just don't care. :)
# firefox -print option depends on http://sites.google.com/site/torisugari/commandlineprint2  
# it's kind of possible that a file inside de .xpi extension must be edited to get bigger pdf . Depends on the html you would like to print. Good html code does not need it. 


####variables

## Date, to be used as reference on tmp files
DATE=`date +%Y%m%d`
## File where all webs to report are listed
WEBSFILE="/home/marc.riera/Desktop/reports/websfile.txt"    # urls to print. lines starting with # will be ignored.
## Where to store all the files. 
WORKDIR="/home/marc.riera/Desktop/reports"
MAILTO="marc.riera@barcelonamedia.org"   # other mails can be added just with a single space between
MAILTEXTFILE=$WEBSFILE         
FFPROFILE="cnm-profile"  #FIREFOX PROFILE - create it with firefox -ProfileManager while no other firefox instances running

##################do not edit under this line
#echo "$DATE - $0"
logger $0
TMPDIR=$WORKDIR/$DATE
test -d $TMPDIR && rm -f $TMPDIR/*.pdf|| mkdir -p $TMPDIR && echo "Create folder $TMPDIR for temporal usage"
REPORT=$WORKDIR/Report_$DATE.pdf

##firefox -print "http://fbmsgga01/ganglia/?m=cpu_report&r=month&s=descending&c=CPU+cluster&h=&sh=1&hc=4&z=small" -printmode pdf -printdelay 5 -printfile ~/Desktop/reports/test.pdf
firefoxprint (){
    web2Print=$1
    outputFile=$2
    #echo "printing $1 on $2"
    env DISPLAY=:0.0 firefox -P $FFPROFILE -no-remote -print "$web2Print" -printmode pdf -printdelay 15 -printfile $outputFile &
    while [ ! -s $outputFile ]; do
          sleep 1
    done
}

##gs -dNOPAUSE -sDEVICE=pdfwrite -sOUTPUTFILE=dospdf.pdf -dBATCH ganglia.pdf test.pdf
pdfjoin (){
    outputFile=$1
    tempdir=$2
    cd $tempdir
    gs -dNOPAUSE -sDEVICE=pdfwrite -sOUTPUTFILE=$outputFile -dBATCH `ls -tr $tmpdir`
    wait
}

sendmail (){
    #echo "Sending mail"
    mutt -s "Report del dia $DATE" -a $REPORT -- $MAILTO < $MAILTEXTFILE
    wait
}

###################################### MAIN
#######################################
COUNTER=0
for web in `cat $WEBSFILE|grep -v '^#'|grep -v '^$'`
do
    firefoxprint $web $TMPDIR/$COUNTER.pdf
    let COUNTER+=1
done
pdfjoin $REPORT $TMPDIR
sendmail
exit 0

Я все еще готов к улучшениям, но сейчас он делает то, что мне нужно.