Shell Script Help - Принять ввод и запустить в BackGround? - PullRequest
5 голосов
/ 10 августа 2011

У меня есть сценарий оболочки, в котором в первой строке я прошу пользователя указать, сколько минут он хочет запустить сценарий:

 #!/usr/bin/ksh
echo "How long do you want the script to run for in minutes?:\c"
read scriptduration
loopcnt=0
interval=1
date2=$(date +%H:%M%S)
(( intervalsec = $interval * 1 ))
totalmin=${1:-$scriptduration}
(( loopmax = ${totalmin} * 60 ))

ofile=/home2/s499929/test.log
echo "$date2 total runtime is $totalmin minutes at 2 sec intervals"
while(( $loopmax > $loopcnt ))
do
  date1=$(date +%H:%M:%S)
   pid=`/usr/local/bin/lsof | grep 16752 | grep LISTEN |awk '{print $2}'` > /dev/null 2>&1
   count=$(netstat -an|grep 16752|grep ESTABLISHED|wc -l| sed "s/ //g")
   process=$(ps -ef | grep $pid | wc -l | sed "s/ //g")
   port=$(netstat -an | grep 16752 | grep LISTEN | wc -l| sed "s/ //g")
  echo "$date1 activeTCPcount:$count activePID:$pid activePIDcount=$process listen=$port" >> ${ofile}
  sleep $intervalsec
  (( loopcnt = loopcnt + 1 ))
done

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

Я попытался просто запустить ./scriptname &, и я получил это:

$ How long do you want the test to run for in minutes:360
ksh: 360:  not found.
[2] + Stopped (SIGTTIN)        ./test.sh &

И сценарий умирает. Возможно ли это, какие-либо предложения о том, как я могу принять этот один вход, а затем запустить в фоновом режиме? Спасибо !!!

Ответы [ 5 ]

3 голосов
/ 10 августа 2011

Вы можете сделать что-то вроде этого:

test.sh arg1 arg2 &

Просто обратитесь к arg1 и arg2 как $ 1 и $ 2 соответственно в скрипте bash. ($ 0 - это название сценария)

Итак,

test.sh 360 &

передаст 360 в качестве первого аргумента скрипту bash или ksh, который в сценарии может именоваться $ 1 .

Итак, первые несколько строк вашего скрипта теперь будут:

#!/usr/bin/ksh
scriptduration=$1
loopcnt=0
...
...
3 голосов
/ 10 августа 2011

С bash вы можете запустить скрипт на переднем плане, а после того, как вы закончили с пользовательским вводом, прервите его, нажав Ctrl-Z.

Затем введите

$ bg %

, и скрипт продолжит работу в фоновом режиме.

1 голос
/ 11 августа 2011

Почему вы получаете то, что вы получаете

Когда вы запускаете скрипт в фоновом режиме, он не может принимать пользовательский ввод.Фактически, программа остановится, если ожидает ввода пользователя, пока не вернется на передний план.Однако вывод должен идти куда-то .Таким образом, вывод выводится на экран (даже если программа работает в фоновом режиме. Таким образом, вы видите подсказку.

Подсказка, которую вы видите при отображении вашей программы, не имеет смысла, потому что вы не можете вводить в подсказкеВместо этого вы вводите 360, и ваша оболочка интерпретирует ее как команду, которую вы хотите, потому что вы не помещаете ее в программу, вы помещаете ее в командную строку.

Вы хотите, чтобы вашаПрограмма должна быть на переднем плане для ввода, но работать в фоновом режиме. Вы не можете сделать оба сразу.

Решения вашей дилеммы

У вас может быть две программы. Первая занимаетввод, а второй запускает реальную программу в фоновом режиме.

Примерно так:

#! /bin/ksh
read time?"How long in seconds do you want to run the job? "
my_actual_job.ksh $time &

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

#! /bin/ksh

readonly MAX_FOREGROUND_TIME=30
read time?"How long in seconds do you want to run the job? "
if [ $time -gt $MAX_FOREGROUND_TIME ]
then
    my_actual_job.ksh $time &
else
    my_actual_job.ksh $time
fi

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

Я полагаю, что есть простой способ узнать, является ли ваша работана заднем плане, но я не могу вспомнить это случайно.Вы можете найти свой текущий идентификатор процесса, посмотрев на $$, затем посмотрев на вывод jobs -p и посмотреть, есть ли этот идентификатор процесса в списке.Тем не менее, я уверен, что кто-то придумает простой способ сказать.

Также возможно, что программа может переместиться в фоновый режим с помощью команды bg $$.

НекоторыеСоветы

Если вы используете Kornshell, вы можете воспользоваться многими специальными функциями Kornshell:

  • print : printКоманда более гибкая и надежная, чем echo.Взгляните на справочную страницу для Kornshell и ознакомьтесь со всеми его функциями.

  • read : вы заметили, что можете использовать форму read var?"prompt" команды read.

  • readonly : Используйте readonly для объявления констант.Таким образом, вы случайно не измените значение этой переменной позже.Кроме того, это хорошая техника программирования.

  • typeset : взгляните на typeset на странице руководства ksh.Команда typeset может помочь вам объявить определенные переменные как числа с плавающей запятой по сравнению с вещественными и может автоматически выполнять такие операции, как заполнение нулями, выравнивание по правому или левому краю и т. Д.в Kornshell:

    • Команды awk и sed также могут делать то, что делает grep, поэтому нет никакой причины фильтровать что-либо через grep, а затем через awkили sed.

    • Вы можете объединить grep с, используя параметр -e.grep foo | grep bar совпадает с grep -e foo -e bar.

    Надеюсь, это поможет.

0 голосов
/ 10 августа 2011

Так вы используете bash или ksh?В bash вы можете сделать это:

{ echo 360 | ./test.sh ; } &

Это может работать и для ksh.

0 голосов
/ 10 августа 2011

Я проверил это с помощью ksh, и это сработало. Хитрость заключается в том, чтобы позволить скрипту вызывать себя со временем ожидания в качестве параметра:

if [ -z "$1" ]; then
    echo "How long do you want the test to run for in minutes:\c"
    read scriptduration
    echo "running task in background"
    $0 $scriptduration &
    exit 0
else
    scriptduration=$1
fi

loopcnt=0
interval=1
# ... and so on
...