Shell脚本帮助 - 接受输入并在BackGround中运行?

时间:2011-08-10 18:31:27

标签: shell scripting ksh

我有一个shell脚本,在第一行中我要求用户输入他们希望脚本运行的分钟数:

 #!/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 个答案:

答案 0 :(得分:3)

使用bash,您可以在前台启动脚本,在完成用户输入后,通过按Ctrl-Z来中断它。

然后输入

$ bg %

并且脚本将继续在后台运行。

答案 1 :(得分:3)

你可以这样做:

test.sh arg1 arg2 &

只需在bash脚本中将 arg1 arg2 分别称为 $ 1 $ 2 。 ($ 0是脚本的名称)

所以,

test.sh 360 &

将传递360作为bash或ksh脚本的第一个参数,在脚本中可以称为 $ 1

所以你的脚本的前几行现在是:

#!/usr/bin/ksh
scriptduration=$1
loopcnt=0
...
...

答案 2 :(得分:1)

为什么你得到了什么

在后台运行脚本时,它无法接受任何用户输入。实际上,如果程序预期用户输入直到其放回前台,程序将冻结。但是,输出必须 某处 。因此,输出进入屏幕(即使程序在后台运行。因此,您会看到提示。

您看到程序显示的提示没有意义,因为您无法在提示符下输入。相反,您输入360并且您的shell将其解释为您想要的命令,因为您没有将它放在程序中,而是将它放在命令提示符中。

您希望程序位于输入的前台,但在后台运行。你不能一次做两件事。

解决您的困境

你可以有两个程序。第一个接受输入,第二个在后台运行实际程序。

这样的事情:

#! /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会话中间显示输出。

我相信有一种简单的方式来判断你的工作是否在后台,但我不记得了。您可以通过查看$$找到当前进程ID,然后查看jobs -p的输出,并查看该进程ID是否在列表中。但是,我相信有人会想出一个简单的方法来说明。

程序也可能通过bg $$命令将自己投入后台。

一些提示

如果您正在运行Kornshell,您可以考虑利用Kornshell的许多特殊功能:

  • 打印print命令比echo更灵活,更强大。查看Kornshell的联机帮助页并查看其所有功能。

  • 阅读:您注意到可以使用读取命令的read var?"prompt"形式。

  • readonly :使用readonly声明常量。这样,您不会在以后意外更改该变量的值。此外,它是很好的编程技术。

  • 排版:在ksh联机帮助页中查看typesettypeset命令可以帮助您将特定变量声明为浮点数与实数,并且可以自动执行零填充,右对齐或左对齐等操作。

一些不是Kornshell特有的东西:

  • awksed命令也可以执行grep所做的操作,因此没有理由通过grep然后通过{{1}过滤某些内容}或awk

  • 您可以使用sed参数合并grep-egrep foo | grep bar相同。

希望这有帮助。

答案 3 :(得分:0)

我用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

答案 4 :(得分:0)

你也在使用bash或ksh吗?在bash中,您可以这样做:

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

它也适用于ksh。