it-swarm.com.ru

Эхо-команда, а потом запустить? (Вроде марка)

Есть ли какой-нибудь способ перевести bash в некий подробный режим, в котором, когда он запускает скрипт Shell, он выводит команду, которую он собирается запустить, прежде чем запускать его? То есть, чтобы можно было увидеть команды, которые были запущены (а также их вывод), аналогично выводу make?

То есть, если запустить скрипт типа Shell

echo "Hello, World"

Я хотел бы следующий вывод

echo "Hello, World"
Hello, World

В качестве альтернативы, можно ли написать функцию bash с именем echo_and_run, которая будет выводить команду, а затем запускать ее?

$ echo_and_run echo "Hello, World"
echo "Hello, World"
Hello, World
15
mjs

Можно использовать printf в bash вместе со спецификатором формата %q, чтобы экранировать аргументы и сохранить пробелы:

function echo_and_run {
  echo "$" "[email protected]"
  eval $(printf '%q ' "[email protected]") < /dev/tty
}
7
mjs

Вы можете сделать свою собственную функцию для команд echo перед вызовом eval.

Bash также имеет функцию отладки. После того, как вы set -x bash отобразите каждую команду перед ее выполнением.

[email protected]:~/dir$ set -x
[email protected]:~/dir$ ls
+ ls --color=auto
a  b  c  d  e  f
28
cnicutar

Чтобы ответить на вторую часть вашего вопроса, вот функция Shell, которая делает то, что вы хотите:

echo_and_run() { echo "[email protected]" ; "[email protected]" ; }

Я использую что-то похожее на это:

echo_and_run() { echo "\$ [email protected]" ; "[email protected]" ; }

которая печатает $ перед командой (она выглядит как приглашение командной строки и проясняет, что это команда). Я иногда использую это в сценариях, когда хочу показать некоторые (но не все) команды, которые он выполняет.

Как уже упоминали другие, он теряет кавычки:

$ echo_and_run echo "Hello, world"
$ echo Hello, world
Hello, world
$ 

но я не думаю, что есть хороший способ избежать этого; Shell удаляет кавычки, прежде чем echo_and_run получит возможность их увидеть. Вы можете написать скрипт, который будет проверять наличие аргументов, содержащих пробелы и другие метасимволы Shell, и добавлять кавычки по мере необходимости (которые все равно не обязательно будут совпадать с кавычками, которые вы фактически ввели).

15
Keith Thompson

Для получения дополнительных временных отметок и информации о вводе/выводе рассмотрите команду annotate-output из Debian s devscripts package:

annotate-output echo hello

Результат:

13:19:08 I: Started echo hello
13:19:08 O: hello
13:19:08 I: Finished with exitcode 0

Теперь найдите файл, который не существует, и обратите внимание на вывод E: for STDERR:

annotate-output ls nosuchfile

Результат:

13:19:48 I: Started ls nosuchfile
13:19:48 E: ls: cannot access 'nosuchfile': No such file or directory
13:19:48 I: Finished with exitcode 2
0
agc

Чтобы добавить к реализациям других, это мой основной сценарий сценария, включая разбор аргументов (что важно, если вы переключаете уровни многословия). 

#!/bin/sh

# Control verbosity
VERBOSE=0

# For use in usage() and in log messages
SCRIPT_NAME="$(basename $0)"

ARGS=()

# Usage function: tells the user what's up, then exits.  ALWAYS implement this.
# Optionally, prints an error message
# usage [{errorLevel} {message...}
function usage() {
    local RET=0
    if [ $# -gt 0 ]; then
        RET=$1; shift;
    fi
    if [ $# -gt 0 ]; then
        log "[$SCRIPT_NAME] ${@}"
    fi
    log "Describe this script"
    log "Usage: $SCRIPT_NAME [-v|-q]" # List further options here
    log "   -v|--verbose    Be more verbose"
    log "   -q|--quiet      Be less verbose"
    exit $RET
}

# Write a message to stderr
# log {message...}
function log() {
    echo "${@}" >&2
}

# Write an informative message with decoration
# info {message...}
function info() {
    if [ $VERBOSE -gt 0 ]; then
        log "[$SCRIPT_NAME] ${@}"
    fi
}

# Write an warning message with decoration
# warn {message...}
function warn() {
    if [ $VERBOSE -gt 0 ]; then
        log "[$SCRIPT_NAME] Warning: ${@}"
    fi
}

# Write an error and exit
# error {errorLevel} {message...}
function error() {
    local LEVEL=$1; shift
    if [ $VERBOSE -gt -1 ]; then
        log "[$SCRIPT_NAME] Error: ${@}"
    fi
    exit $LEVEL
}

# Write out a command and run it
# vexec {minVerbosity} {prefixMessage} {command...}
function vexec() {
    local LEVEL=$1; shift
    local MSG="$1"; shift
    if [ $VERBOSE -ge $LEVEL ]; then
        echo -n "$MSG: "
        local CMD=( )
        for i in "${@}"; do
            # Replace argument's spaces with ''; if different, quote the string
            if [ "$i" != "${i/ /}" ]; then
                CMD=( ${CMD[@]} "'${i}'" )
            else
                CMD=( ${CMD[@]} $i )
            fi
        done
        echo "${CMD[@]}"
    fi
    ${@}
}

# Loop over arguments; we'll be shifting the list as we go,
# so we keep going until $1 is empty
while [ -n "$1" ]; do
    # Capture and shift the argument.
    ARG="$1"
    shift
    case "$ARG" in
        # User requested help; sometimes they do this at the end of a command
        # while they're building it.  By capturing and exiting, we avoid doing
        # work before it's intended.
        -h|-\?|-help|--help)
            usage 0
            ;;
        # Make the script more verbose
        -v|--verbose)
            VERBOSE=$((VERBOSE + 1))
            ;;
        # Make the script quieter
        -q|--quiet)
            VERBOSE=$((VERBOSE - 1))
            ;;
        # All arguments that follow are non-flags
        # This should be in all of your scripts, to more easily support filenames
        # that start with hyphens.  Break will bail from the `for` loop above.
        --)
            break
            ;;
        # Something that looks like a flag, but is not; report an error and die
        -?*)
            usage 1 "Unknown option: '$ARG'" >&2
            ;;
        #
        # All other arguments are added to the ARGS array.
        *)
            ARGS=(${ARGS[@]} "$ARG")
            ;;
    esac
done
# If the above script found a '--' argument, there will still be items in $*;
# move them into ARGS
while [ -n "$1" ]; do
    ARGS=(${ARGS[@]} "$1")
    shift
done

# Main script goes here.

Потом...

vexec 1 "Building myapp.c" \
    gcc -c myapp.c -o build/myapp.o ${CFLAGS}

Примечание. Это не распространяется на командные каналы; вам нужно bash -c такого рода вещи или разбить их на промежуточные переменные или файлы.

0
Fordi

Два полезных параметра оболочки, которые можно добавить в командную строку bash или с помощью команды set в сценарии или интерактивном сеансе:

  • -v Печатать строки ввода в оболочке по мере их чтения.
  • -x После развертывания каждой простой команды, команды for, команды case, select или арифметической команды for выведите расширенное значение PS4, за которым следует команда и ее расширенное значение аргументы или связанный список слов.
0
Toby Speight