【问题标题】:Bash script to capture input, run commands, and print to file用于捕获输入、运行命令和打印到文件的 Bash 脚本
【发布时间】:2011-11-22 21:41:25
【问题描述】:

我正在尝试做家庭作业,这非常令人困惑。我不确定教授的示例是使用 Perl 还是 bash,因为它没有标题。基本上,我只需要帮助解决问题的核心:捕获输入并输出它。这是作业:

  1. 在会话中,提供包含工作目录的命令提示符,例如, $./logger/home/it244/it244/hw8$

  2. 接受用户的命令,执行它们,并在屏幕上显示输出。

  3. 在会话期间,创建一个临时文件“PID.cmd”(PID是进程ID)来存储命令历史,格式如下(索引:命令):

    1:ls
    2:ls -l

  4. 如果脚本被CTRL+C(信号2)中止,输出消息“被ctrl+c中止”。

  5. 当您退出记录会话时(通过“exit”或CTRL+C),

    一个。删除临时文件

    b.打印出会话中的命令总数以及成功/失败的命令数(根据退出状态)。

这是我目前的代码(运行不顺利,我不会尝试运行它):

  #!/bin/sh
  trap 'exit 1' 2
  trap 'ctrl-c' 2

  echo $(pwd)
  while true
  do
    read -p command
    echo "$command:" $command >> PID.cmd
 done

目前当我运行这个脚本时,我得到了

command read: 10: arg count

是什么原因造成的?

======更新=========

好吧,我取得了一些进展,但它并不喜欢我的 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 

【问题讨论】:

  • 什么特别困扰着你?您没有太多工作要做,因为您似乎才刚刚开始触及表面。
  • 添加评论 我只是在看我教授的幻灯片和示例,但它们很少,所以我认为至少可以让我输入和输出命令,但是我收到上面发布的错误并且无法 ctrl -c
  • 越来越近了!我发布了一个在 SLES11SP1 上测试的工作示例。我相信你会逐行检查它,而不仅仅是把它上交。特别是,如果你按原样使用它,那里有一些代码来确定你必须向老师解释的 cwd . :-) 顺便说一句,+1 表示努力。

标签: linux bash io


【解决方案1】:

这可以在 bash 或 perl 或其他中实现。

一些提示可以帮助您开始使用 bash:

问题 1:命令提示符 /logger/home/it244/it244/hw8
1) 确保用户 .bashrc 设置文件中的提示格式:查看 PS1 数据以获取类似 debian 的发行版。
2) cd 进入你的 bash 脚本中的那个目录。

问题 2:运行用户命令
1)获取用户输入

read -p "command : " input_cmd

2) 运行用户命令到 STDOUT

bash -c "$input_cmd"

3) 跟踪用户输入命令退出代码

 echo $?

如果一切正常,应该以“0”退出(您也可以在命令手册页中找到退出代码)。

3) 如果退出代码是 Ok 则跟踪命令 PID

 echo $$ >> /tmp/pid_Ok

但请注意问题是保持用户命令输入,而不是此处显示的 PID 本身。

4) 出口陷阱
请参阅 man trap,因为您误解了 this 的用法:您可以创建一个在捕获的退出或 CTRL/C 信号上调用的函数。

5) 在 while 循环中增加索引(在退出代码条件下)

index=0
while ...
   do
   ...
   ((index++)) 
   done

我猜你有足够的时间开始你的家庭作业。

【讨论】:

    【解决方案2】:

    由于发布的示例使用了 sh,我将在回复中使用它。您需要将每个需求分解为其特定的支持代码行。例如,为了“提供包含工作目录的命令提示符”,您需要将当前工作目录实际打印为 read 命令的提示字符串,而不是通过设置 $PS 变量.这会产生一个read 命令,如下所示:

    read -p "`pwd -P`\$ " _command
    

    (我对私有变量使用前导下划线 - 只是风格问题。)

    类似地,在陷阱或正常退出时执行多项操作的要求表明应创建一个函数,然后该函数可以由陷阱调用或根据用户输入退出循环。如果你想漂亮地打印退出消息,你也可以将它包装在 echo 命令中,它可能看起来像这样:

    _cleanup() {
       rm -f $_LOG
       echo
       echo $0 ended with $_success successful commands and $_fail unsuccessful commands.
       echo
       exit 0
    }
    

    因此,在分析每个需求之后,您需要一些计数器和一些胶水代码(例如 while 循环)来包装它们。结果可能如下所示:

    #/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 $0 ended with $_success successful commands and $_fail unsuccessful commands.
       echo
       exit 0
    }
    
    # Where are we?  Get absolute path of $0
    _abs_path=$( cd -P -- "$(dirname -- "$(command -v -- "$0")")" && 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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-01-04
      • 1970-01-01
      • 1970-01-01
      • 2011-11-13
      • 2015-12-02
      • 2014-05-15
      相关资源
      最近更新 更多