Скрипт Bash для ввода, запуска команд и печати в файл - PullRequest
2 голосов
/ 23 ноября 2011

Я пытаюсь выполнить домашнее задание, и это очень сбивает с толку. Я не уверен, является ли пример профессора Perl или bash, поскольку у него нет заголовка. По сути, мне просто нужна помощь в решении проблемы: захват ввода и вывод его. Вот назначение:

  1. В сеансе предоставьте командную строку, которая включает рабочий каталог, например, $./logger/home/it244/it244/hw8$

  2. Примите команды пользователя, выполните их и отобразите вывод на экране.

  3. Во время сеанса создайте временный файл «PID.cmd» (PID - это идентификатор процесса) для сохранения истории команд в следующем формате (индекс: команда):

    1: ls
    2: ls -l

  4. Если сценарий прерывается с помощью CTRL + C (сигнал 2), выведите сообщение «abtred ctrl + c».

  5. Когда вы выходите из сеанса ведения журнала (либо «выходом», либо CTRL + C ),

    а. Удалить временный файл

    б. Распечатайте общее количество команд в сеансе и количество успешных / неудачных команд (в зависимости от состояния выхода).

Вот мой код (который не удался, я бы не стал его запускать):

  #!/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 

Ответы [ 2 ]

2 голосов
/ 23 ноября 2011

Это может быть достигнуто в bash, perl или других.

Некоторые подсказки для начала работы в bash:

вопрос 1 : командная строка / регистратор / home / it244 / it244 / hw8
1) Убедитесь, что формат приглашения указан в пользовательском установочном файле .bashrc: см. Данные PS1 для дистрибутивов, подобных Debian.
2) Перейдите в этот каталог внутри вашего bash-скрипта.

вопрос 2 : выполнить команду пользователя
1) получить пользовательский ввод

read -p "command : " input_cmd

2) запустить пользовательскую команду для STDOUT

bash -c "$input_cmd"

3) Отслеживание кода выхода команды ввода пользователя

 echo $?

Должен завершиться с «0», если все работало нормально (коды выхода также можно найти в справочных страницах команд).

3) Отслеживать PID команды, если код выхода в порядке

 echo $$ >> /tmp/pid_Ok

Но будьте осторожны, вопрос заключается в том, чтобы сохранить ввод команды пользователя, а не сам PID, как показано здесь.

4) ловушка на выходе
смотрите на ловушку человека, поскольку вы неправильно поняли, как использовать это: вы можете создать функцию, вызываемую для сигналов прерывного выхода или CTRL / C.

5) увеличить индекс в цикле while (при условии кода выхода)

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

Полагаю, у вас достаточно, чтобы начать домашнюю работу.

1 голос
/ 23 ноября 2011

Поскольку в опубликованном примере используется sh, я буду использовать это в своем ответе.Вам необходимо разбить каждое требование на отдельные строки вспомогательного кода.Например, чтобы «предоставить командную строку, содержащую рабочий каталог», вам необходимо распечатать текущий рабочий каталог в виде строки приглашения для команды read , а не путем установки переменной $PS.Это приводит к команде read, которая выглядит следующим образом:

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

(я использую начальные подчеркивания для частных переменных - просто вопрос стиля.)

Аналогично, требуется выполнить несколькоТо, что находится в ловушке или обычном выходе, предполагает создание функции, которая затем может быть вызвана ловушкой или выйти из цикла на основе пользовательского ввода.Если вы хотите распечатать сообщение о выходе, вы можете также обернуть его в команды эха, и оно может выглядеть так:

_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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...