我有一个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 &
脚本死了。这是可能的,关于我如何接受这一个输入然后在后台运行的任何建议?感谢!!!
答案 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联机帮助页中查看typeset
。 typeset
命令可以帮助您将特定变量声明为浮点数与实数,并且可以自动执行零填充,右对齐或左对齐等操作。
一些不是Kornshell特有的东西:
awk
和sed
命令也可以执行grep
所做的操作,因此没有理由通过grep
然后通过{{1}过滤某些内容}或awk
。
您可以使用sed
参数合并grep
。 -e
与grep 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。