Shell 脚本帮助——接受输入并在后台运行?
我有一个 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 &
剧本就死了。这可能吗,关于如何接受这一输入然后在后台运行有什么建议吗?谢谢!!!
I have a shell script in which in the first line I ask the user to input how many minutes they want the script to run for:
#!/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
It works great if I kick it off an input the values manually. But if I want to run this for 3 hours I need to kick off the script to run in the background.
I have tried just running ./scriptname & and I get this:
$ How long do you want the test to run for in minutes:360
ksh: 360: not found.
[2] + Stopped (SIGTTIN) ./test.sh &
And the script dies. Is this possible, any suggestions on how I can accept this one input and then run in the background?? Thanks!!!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
你可以这样做:
只需将 arg1 和 arg2 分别引用为 $1 和 $2,在bash 脚本。 ($0 是脚本的名称)
因此,
会将 360 作为第一个参数传递给 bash 或 ksh 脚本,在脚本中可以将其称为 $1。
所以你的脚本的前几行现在是:
You could do something like this:
Just refer to arg1 and arg2 as $1 and $2, respectively, in the bash script. ($0 is the name of the script)
So,
will pass 360 as the first argument to the bash or ksh script which can be referred to as $1 in the script.
So the first few lines of your script would now be:
使用 bash,您可以在前台启动脚本,完成用户输入后,按 Ctrl-Z 中断它。
然后输入
,脚本将继续在后台运行。
With bash you can start the script in the foreground and after you finished with the user input, interrupt it by hitting Ctrl-Z.
Then type
and the script will continue to run in the background.
为什么您会得到您所得到的结果
当您在后台运行脚本时,它无法接受任何用户输入。事实上,如果程序需要用户输入,它将冻结,直到它被放回前台。然而,输出必须到达某个地方。因此,输出会显示到屏幕上(即使程序在后台运行。因此,您会看到提示符。
您看到程序显示的提示符是没有意义的,因为您无法在提示符下输入。相反,您输入
360
并且您的 shell 会将其解释为您想要的命令,因为您没有将其放入程序中,而是将其放入命令提示符中您希望程序位于前台 。输入,但在后台运行。无法同时执行这两项
操作
。您可以有两个程序,第一个程序接受输入,第二个程序在后台运行实际程序
:
事实上,您甚至可以有一个运行机制。如果时间超过一定限制,则作业在后台运行,但否则在前台运行作业。
另请记住,如果您的作业在后台,则它无法打印到屏幕,您可以将输出重定向到其他地方。不,它会打印到屏幕上不合时宜的时候。例如,您可能正在 VI 中编辑文件,突然输出出现在 VI 会话的中间。
我相信有一种简单的方法可以判断您的工作是否在后台,但我无法立即记住它。您可以通过查看
$$
找到当前的进程 ID,然后查看jobs -p
的输出并查看该进程 ID 是否在列表中。不过,我相信有人会想出一个简单的方法来区分。程序也有可能通过 bg $$ 命令将自身置于后台。
一些提示
如果您正在运行 Kornshell,您可能会考虑利用 Kornshell 的许多特殊功能:
print:
print
命令比 <代码>回显。查看 Kornshell 的联机帮助页并了解其所有功能。read:您注意到可以使用读取命令的
read var?"prompt"
形式。readonly:使用readonly声明常量。这样,您以后就不会意外更改该变量的值。此外,这是很好的编程技术。
typeset:查看 ksh 联机帮助页中的
typeset
。typeset
命令可以帮助您将特定变量声明为浮点与实数,并且可以自动执行诸如零填充、右对齐或左对齐等操作。一些非 Kornshell 特有的操作:
awk
和sed
命令也可以执行grep
的操作,因此没有理由通过grep
过滤某些内容,然后通过 awk 或sed
。您可以使用
-e
参数组合grep
。 grep foo | | grep foo | grep foo | grep foo | grep foo | grep foo grep bar 与grep -e foo -e bar
相同。希望这有帮助。
Why You're Getting What You're Getting
When you run the script in the background, it can't take any user input. In fact, the program will freeze if it expects user input until its put back in the foreground. However, output has to go somewhere. Thus, the output goes to the screen (even though the program is running in the background. Thus, you see the prompt.
The prompt you see your program displaying is meaningless because you can't input at the prompt. Instead, you type in
360
and your shell is interpreting it as a command you want because you're not putting it in the program, you're putting it in the command prompt.You want your program to be in the foreground for the input, but run in the background. You can't do both at once.
Solutions To Your Dilemma
You can have two programs. The first takes the input, and the second runs the actual program in the background.
Something like this:
In fact, you could even have a mechanism to run the job in the background if the time is over a certain limit, but otherwise run the job in the foreground.
Also remember if your job is in the background, it cannot print to the screen. You can redirect the output elsewhere, but if you don't, it'll print to the screen at inopportune times. For example, you could be in VI editing a file, and suddenly have the output appear smack in the middle of your VI session.
I believe there's an easy way to tell if your job is in the background, but I can't remember it offhand. You could find your current process ID by looking at
$$
, then looking at the output ofjobs -p
and see if that process ID is in the list. However, I'm sure someone will come up with an easy way to tell.It is also possible that a program could throw itself into the background via the
bg $$
command.Some Hints
If you're running Kornshell, you might consider taking advantage of many of Kornshell's special features:
print: The
print
command is more flexible and robust thanecho
. Take a look at the manpage for Kornshell and see all of its features.read: You notice that you can use the
read var?"prompt"
form of the read command.readonly: Use readonly to declare constants. That way, you don't accidentally change the value of that variable later. Besides, it's good programming technique.
typeset: Take a look at
typeset
in the ksh manpage. Thetypeset
command can help you declare particular variables as floating point vs. real, and can automatically do things like zero fill, right or left justify, etc.Some things not specific to Kornshell:
The
awk
andsed
commands can also do whatgrep
does, so there's no reason to filter something throughgrep
and then throughawk
orsed
.You can combine
grep
s by using the-e
parameter.grep foo | grep bar
is the same asgrep -e foo -e bar
.Hope this helps.
我已经用 ksh 测试过它并且有效。诀窍是让脚本以等待时间作为参数来调用自身:
I've tested this with ksh and it worked. The trick is to let the script call itself with the time to wait as parameter:
那么你使用的是bash还是ksh?在 bash 中,您可以这样做:
它也适用于 ksh。
So are you using bash or ksh? In bash, you can do this:
It could work for ksh also.