LINUX.ORG.RU
ФорумAdmin

Замена одной комманды другой.

 


0

1

Бывает необходимо запустить такую команду (аргументы у /path/scrypt могут быть разные):

# /usr/bin/su - user -s /bin/sh -c "/path/scrypt -c -d 'string1 string2'" 
Хотел сделать возможность запускать туже команду но так:
/path/new_scrypt.sh -c -d 'string1 string2'
Ну никак мне не удаётся написать new_scrypt.sh так, что бы он все полученные параметры ($@), включая апострофы, передавал в том же виде в /path/scrypt при запуске его через su. Как правильно написать bash-скрипт?


Ответ на: комментарий от Bad_ptr

Содержит две строки:

#!/bin/bash
/usr/bin/su - user -s /bin/sh -c "/path/scrypt $@" 
Но вот так не работает, параметры не передаются правильно в /path/scrypt.

Viper
() автор топика
Последнее исправление: Viper (всего исправлений: 1)
... "${@@Q}"

Если баш старенький, то @Q нужно заменить на printf -v arr '%q' "$@"; ... "${arr[@]}". и /bin/sh лучше заменить на /bin/bash, т.к. теоритечески /bin/sh может не подойти экранирование, выполненное баш.

anonymous
()

Через su -c точно не сделаете. Без костылей по крайней мере. Поскольку там надо все слепить в одну строку и заново распарсить, вся разбивка в "$@" пойдёт насмарку. А вот у sudo интерфейс гораздо лучше, и там можно скормить нормально побитые аргументы из "$@". Вот так:

[d_a@home ~]$ new_scrypt() { /usr/bin/sudo -u root printf "<%s> "  "$@"; }
[d_a@home ~]$ new_scrypt a\ b \'c\' d
<a b> <'c'> <d> [d_a@home ~]$ 
Поэтому sudo и следует использовать, а su выкинуть на свалку.

d_a ★★★★★
()

комманды

команду

Хм. Будь бдительней!

Stahl ★★☆
()
Ответ на: комментарий от Viper

Примерно так можно

Вот:

$: cat ./test.sh

#!/bin/sh

nsl__output () {
    printf %s "$@"
}

nsl_output () {
    nsl__output "$@"
}


nsl_quote_with_single_quotes () {
    _nsl_tmp_arg="$(nsl_sed_surround_single_by_double_and_single_quotes "$@"x)"
    nsl_output "'${_nsl_tmp_arg%x}'"
}

nsl_sed_surround_single_by_double_and_single_quotes () {
    nsl__output "$@" | sed -e 's/'"'"'/'"'"'"'"'"'"'"'"'/g'
}

nsl_args_slice_to_list () {
    _nsl_arg_tmp='slice' #mode
    case "$1" in
        [0-9]*) ;;
        splice)
            _nsl_arg_tmp='splice'
            shift
            ;;
    esac

    _nsl_arg_id="$1" #start id
    shift
    _nsl_arg_id1="$1" #length of slice
    shift
    while [ 0 -gt "$_nsl_arg_id" ]; do
        _nsl_arg_id=$(($# + _nsl_arg_id))
    done
    while [ 0 -gt "$_nsl_arg_id1" ]; do
        _nsl_arg_id1=$(($# + 1 - _nsl_arg_id + _nsl_arg_id1))
    done

    _nsl_args_tmp=""

    if [ xsplice = x"$_nsl_arg_tmp" ]; then
        _nsl_arg_tmp="$1" # string to append
        shift
        while [ 0 -lt "$_nsl_arg_id" ]; do
            _nsl_args_tmp="${_nsl_args_tmp}$(nsl_quote_with_single_quotes "$1") "
            shift
            _nsl_arg_id=$(($_nsl_arg_id - 1))
        done
        _nsl_args_tmp="${_nsl_args_tmp}$_nsl_arg_tmp"
        while [ 0 -lt "$_nsl_arg_id1" ]; do
            shift
            _nsl_arg_id1=$((_nsl_arg_id1 - 1))
        done
        while [ 0 -lt $# ]; do
            _nsl_args_tmp="${_nsl_args_tmp}$(nsl_quote_with_single_quotes "$1") "
            shift
        done
    else
        while [ 0 -lt "$_nsl_arg_id" ]; do
            shift
            _nsl_arg_id=$((_nsl_arg_id - 1))
        done
        while [ 0 -lt "$_nsl_arg_id1" -a 0 -lt $# ]; do
            _nsl_args_tmp="${_nsl_args_tmp}$(nsl_quote_with_single_quotes "$1") "
            shift
            _nsl_arg_id1=$((_nsl_arg_id1 - 1))
        done
    fi

    nsl_output "${_nsl_args_tmp% }"
}

nsl_args_to_list () {
    nsl_args_slice_to_list 0 -1 "$@"
}

command_string='"'"/path/scrypt $(nsl_args_to_list "$@")"'"'

/usr/bin/su - user -s /bin/sh -c "eval $command_string"

Bad_ptr ★★★★★
()
Ответ на: комментарий от d_a

может сработает может нет 50/50
я вообще не понимаю чё этот /usr/bin/su делает
мне он пишет Sessions still open, not unmounting
я аж ахренел
какой нафиг unmounting, неужто ТС пропихнул через меня на комп патч бармина

Bad_ptr ★★★★★
()
Ответ на: комментарий от d_a

Вот такой скрипт:

#!/bin/bash -x
printf -v arr '%q ' "$@"; /usr/bin/su - user -s "/bin/bash" -c "/path/scrypt" "${arr[@]}"
Команда:
./my_scrypt.sh -c -d 'string1 string2'
Выдаёт такое:
+ printf -v arr '%q ' -c -d 'string1 string2'
+ /usr/bin/su - user -s /bin/bash -c /path/scrypt '-c -d string1\ string2 '
-bash: -d: command not found

Viper
() автор топика
#!/bin/sh

args=
for i; do
        args="$args '$i'"
done
sh -c "$args"

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

vodz ★★★★★
()
Последнее исправление: vodz (всего исправлений: 1)
Ответ на: комментарий от Viper

Потому что вы делаете фигню.

-c "/path/scrypt" "${arr[@]}"

вот это фигня. Всё что надо для -c должно уехать одним аргументом.

Если надо именно su (хотя я советовал sudo), то надо так:
[d_a@home ~]$ fun() { printf -v arr '%q ' "$@"; /bin/su -s /bin/sh -c "$arr" root; }
[d_a@home ~]$ fun printf "<%s> " 1\ 2 3\ 4
Пароль: 
<1 2> <3 4> [d_a@home ~]$ 
Upd: arr это не массив, обновил пост.

d_a ★★★★★
()
Последнее исправление: d_a (всего исправлений: 1)
Ответ на: комментарий от Viper

Попробуй

#!/bin/bash -x
printf -v qstr '%q ' "$@"
/usr/bin/su - user -s 'qstr="$qstr" /bin/bash' -c '/path/scrypt "$qstr"'

anonymous
()
Ответ на: комментарий от d_a

sudo нет, очень обрезанная версия Linux на одной железячке. Большое спасибо Вам, удалось таки сделать то, что требовалось.

Viper
() автор топика
Ответ на: комментарий от Viper

Ну я так и понял, тогда да, остаётся только костылём -- генерируем квотинг (%q), загоняем скаляр в -c, потом оно обратно (надеюсь правильно) распарсится тем что указано в -s :)

d_a ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.