用于捕获输入、运行命令和打印到文件的 Bash 脚本
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/8234206/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Bash script to capture input, run commands, and print to file
提问by BillPull
I am trying to do a homework assignment and it is very confusing. I am not sure if the professor's example is in Perl or bash, since it has no header. Basically, I just need help with the meat of the problem: capturing the input and outputting it. Here is the assignment:
我正在尝试做家庭作业,这很令人困惑。我不确定教授的例子是 Perl 还是 bash,因为它没有标题。基本上,我只需要解决问题的关键:捕获输入并输出它。这是任务:
In the session, provide a command prompt that includes the working directory, e.g.,
$./logger/home/it244/it244/hw8$Accept user's commands, execute them, and display the output on the screen.
During the session, create a temporary file “PID.cmd” (PID is the process ID) to store the command history in the following format (index: command):
1:
ls
2:ls -lIf the script is aborted by CTRL+C(signal 2), output a message “aborted by ctrl+c”.
When you quit the logging session (either by “exit” or CTRL+C),
a. Delete the temporary file
b. Print out the total number of the commands in the session and the numbers of successful/failed commands (according to the exit status).
在会话中,提供包含工作目录的命令提示符,例如,
$./logger/home/it244/it244/hw8$接受用户的命令,执行它们,并在屏幕上显示输出。
在会话期间,创建一个临时文件“PID.cmd”(PID 为进程 ID)以如下格式(索引:命令)存储命令历史记录:
1:
ls
2:ls -l如果脚本被CTRL+ C(信号 2)中止,则输出消息“被 ctrl+c 中止”。
当您退出日志记录会话时(通过“exit”或“ CTRL+” C),
一种。删除临时文件
湾 打印出会话中的命令总数和成功/失败的命令数(根据退出状态)。
Here is my code so far (which did not go well, I would not try to run it):
到目前为止,这是我的代码(效果不佳,我不会尝试运行它):
#!/bin/sh
trap 'exit 1' 2
trap 'ctrl-c' 2
echo $(pwd)
while true
do
read -p command
echo "$command:" $command >> PID.cmd
done
Currently when I run this script I get
目前,当我运行这个脚本时,我得到
command read: 10: arg count
What is causing that?
这是什么原因造成的?
======UPDATE=========
======更新========
Ok I made some progress not quite working all the way it doesnt like my bashtrap or incremental index
好的,我取得了一些进展,但它并不喜欢我的 bashtrap 或增量索引
#!/bin/sh
index=0
trap bashtrap INT
bashtrap(){
echo "CTRL+C aborting bash script"
}
echo "starting to log"
while :
do
read -p "command:" inputline
if [ $inputline="exit" ]
then
echo "Aborting with Exit"
break
else
echo "$index: $inputline" > output
$inputline 2>&1 | tee output
(( index++ ))
fi
done
采纳答案by T.Rob
Since the example posted used sh, I'll use that in my reply. You need to break down each requirement into its specific lines of supporting code. For example, in order to "provide a command prompt that includes the working directory" you need to actually print the current working directory as the prompt string for the readcommand, not by setting the $PSvariable. This leads to a readcommand that looks like:
由于发布的示例使用了 sh,我将在回复中使用它。您需要将每个需求分解为特定的支持代码行。例如,为了“提供包含工作目录的命令提示符”,您需要实际打印当前工作目录作为读取命令的提示字符串,而不是通过设置$PS变量。这会导致一个如下所示的read命令:
read -p "`pwd -P`$ " _command
(I use leading underscores for private variables - just a matter of style.)
(我对私有变量使用前导下划线 - 只是风格问题。)
Similarly, the requirement to do several things on either a trap or a normal exit suggests a function should be created which could then either be called by the trap or to exit the loop based on user input. If you wanted to pretty-print the exit message, you might also wrap it in echo commands and it might look like this:
类似地,需要在陷阱或正常退出时执行多项操作,这表明应该创建一个函数,然后该函数可以被陷阱调用或根据用户输入退出循环。如果你想漂亮地打印退出消息,你也可以将它包装在 echo 命令中,它可能看起来像这样:
_cleanup() {
rm -f $_LOG
echo
echo #/usr/bin/sh
# Define a function to call on exit
_cleanup() {
# Remove the log file as per specification #5a
rm -f $_LOG
# Display success/fail counts as per specification #5b
echo
echo read -p "command : " input_cmd
ended with $_success successful commands and $_fail unsuccessful commands.
echo
exit 0
}
# Where are we? Get absolute path of bash -c "$input_cmd"
_abs_path=$( cd -P -- "$(dirname -- "$(command -v -- " echo $?
")")" && pwd -P )
# Set the log file name based on the path & PID
# Keep this constant so the log file doesn't wander
# around with the user if they enter a cd command
_LOG=${_abs_path}/$$.cmd
# Print ctrl+c msg per specification #4
# Then run the cleanup function
trap "echo aborted by ctrl+c;_cleanup" 2
# Initialize counters
_line=0
_fail=0
_success=0
while true
do
# Count lines to support required logging format per specification #3
((_line++))
# Set prompt per specification #1 and read command
read -p "`pwd -P`$ " _command
# Echo command to log file as per specification #3
echo "$_line: $_command" >>$_LOG
# Arrange to exit on user input with value 'exit' as per specification #5
if [[ "$_command" == "exit" ]]
then
_cleanup
fi
# Execute whatever command was entered as per specification #2
eval $_command
# Capture the success/fail counts to support specification #5b
_status=$?
if [ $_status -eq 0 ]
then
((_success++))
else
((_fail++))
fi
done
ended with $_success successful commands and $_fail unsuccessful commands.
echo
exit 0
}
So after analyzing each of the requirements, you'd need a few counters and a little bit of glue code such as a while loop to wrap them in. The result might look like this:
因此,在分析了每个需求之后,您需要一些计数器和一点点胶水代码(例如 while 循环)来包装它们。结果可能如下所示:
echo $$ >> /tmp/pid_Ok
回答by hornetbzz
This can be achieved in bash or perl or others.
这可以在 bash 或 perl 或其他程序中实现。
Some hints to get you started in bash :
一些让你开始使用 bash 的提示:
question 1: command prompt /logger/home/it244/it244/hw8
1) make sure of the prompt format in the user .bashrc setup file: see PS1 data for debian-like distros.
2) cd into that directory within you bash script.
问题 1:命令提示符 /logger/home/it244/it244/hw8
1) 确保用户 .bashrc 设置文件中的提示格式:请参阅类似 debian 的发行版的 PS1 数据。
2) cd 进入 bash 脚本中的那个目录。
question 2: run the user command
1) get the user input
问题 2:运行用户命令
1) 获取用户输入
index=0
while ...
do
...
((index++))
done
2) run the user command to STDOUT
2)运行用户命令到STDOUT
##代码##3) Track the user input command exit code
3)跟踪用户输入命令退出码
##代码##Should exit with "0" if everything worked fine (you can also find exit codes in the command man pages).
如果一切正常,应该以“0”退出(您也可以在命令手册页中找到退出代码)。
3) Track the command PID if the exit code is Ok
3) 如果退出代码正常,则跟踪命令 PID
##代码##But take care the question is to keep the user command input, not the PID itself as shown here.
但请注意,问题是保留用户命令输入,而不是此处所示的 PID 本身。
4) trap on exit
see man trap as you misunderstood the use of this : you may create a function called on the catched exit or CTRL/C signals.
4) 退出时的陷阱
请参阅 man trap ,因为您误解了 this 的用法:您可以创建一个在捕获的退出或 CTRL/C 信号上调用的函数。
5) increment the index in your while loop (on the exit code condition)
5)增加while循环中的索引(在退出代码条件下)
##代码##I guess you have enough to start your home work.
我想你有足够的时间开始你的家庭作业。

