Предотвратить ssh от разрушения параметров сценария оболочки - PullRequest
6 голосов
/ 06 июля 2011

У меня есть скрипт, который, по сути, является оберткой вокруг исполняемого файла с тем же именем на другом компьютере. Ради примера, я оберну здесь printf. Мой текущий скрипт выглядит так:

#!/bin/bash
ssh user@hostname.tld. printf "$@"

К сожалению, это прерывается, когда один из аргументов содержит пробел, например, я ожидал бы, что следующие команды приведут к идентичным выводам.

~$ ./wrap_printf "%s_%s" "hello world" "1"
hello_world1_
~$ printf "%s_%s" "hello world" "1"
hello world_1

Проблема становится еще хуже, когда (выходят) новые строки. Как бы мне правильно избежать моих аргументов здесь?

Ответы [ 4 ]

7 голосов
/ 06 июля 2011

Основано на ответе Питера Лайонса, но также допускаются кавычки внутри аргументов:

#!/bin/bash
QUOTE_ARGS=''
for ARG in "$@"
do
  ARG=$(printf "%q" "$ARG")
  QUOTE_ARGS="${QUOTE_ARGS} $ARG"
done

ssh user@hostname.tld. "printf ${QUOTE_ARGS}"

Это работает для всего, что я до сих пор тестировал, кроме новых строк:

$ /tmp/wrap_printf "[-%s-]" "hello'\$t\""
[-hello'$t"-]
5 голосов
/ 06 июля 2011
#!/bin/sh
QUOTE_ARGS=''
for ARG in "$@"
do
  QUOTE_ARGS="${QUOTE_ARGS} '${ARG}'"
done
ssh user@hostname.tld. "${QUOTE_ARGS}"

Это работает для пробелов.Это не работает, если аргумент имеет встроенную одинарную кавычку.

2 голосов
/ 06 июля 2011

Правильно процитировать цитаты довольно сложно, а сделать это в bash (в общем и целом) практически невозможно.

Использование Perl:

#!/usr/bin/perl
use Net::OpenSSH;
my $ssh = Net::OpenSSH->new('user@hostname');
$ssh->system('printf', @ARGV);
1 голос
/ 30 января 2013

Основываясь на ответах Керта и Питера Лайонса, вот обертка для ssh; я называю это "sshsystem". (также доступно в https://gist.github.com/4672115)

#!/bin/bash

# quote command in ssh call to prevent remote side from expanding any arguments
# uses bash printf %q for quoting - no idea how compatible this is with other shells.
# /8079534/predotvratit-ssh-ot-razrusheniya-parametrov-stsenariya-obolochki

sshargs=()

while (( $# > 0 )); do
    case "$1" in
    -[1246AaCfgKkMNnqsTtVvXxYy])
        # simple argument
        sshargs+=("$1")
        shift
        ;;
    -[bcDeFIiLlmOopRSWw])
        # argument with parameter
        sshargs+=("$1")
        shift
        if (( $# == 0 )); then
            echo "missing second part of long argument" >&2
            exit 99
        fi
        sshargs+=("$1")
        shift
        ;;
    -[bcDeFIiLlmOopRSWw]*)
        # argument with parameter appended without space
        sshargs+=("$1")
        shift
        ;;
    --)
        # end of arguments
        sshargs+=("$1")
        shift
        break
        ;;
    -*)
        echo "unrecognized argument: '$1'" >&2
        exit 99
        ;;
    *)
        # end of arguments
        break
        ;;
    esac
done


# user@host
sshargs+=("$1")
shift

# command - quote
if (( $# > 0 )); then
    # no need to make COMMAND an array - ssh will merge it anyway
    COMMAND=
    while (( $# > 0 )); do
        arg=$(printf "%q" "$1")
        COMMAND="${COMMAND} ${arg}"
        shift
    done
    sshargs+=("${COMMAND}")
fi

exec ssh "${sshargs[@]}"
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...