LINUX.ORG.RU

Bash, функция в скрипте не определяется как функция

 , ,


0

1

Всем привет

Делаю скрипт для бэкапа, заодно разбираюсь с функциями, наваял вот такое:

server=$1
user=$2
cmd () {
mysqldump -u $1 -p$2 $3 | gzip > $home/backup/$1.tar.gz
}
ssh -l $2@$1 cmd ${list_db:0} ${list_pass:0} ${list_db:0}

ну и делаю:

bash -x backup_from_hosting.sh 1.2.3.4 username243:
+ ssh -l username243@1.2.3.4 cmd user_arr pass_arr bd_arr

Видно, что «cmd» не интерпретируется как функция. Что не так?



Последнее исправление: Aborigen1020 (всего исправлений: 2)

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

намекаете, что удаленный хост не знает ни про какую cmd? Но ведь параметры для функции подставляются корректно.

Aborigen1020
() автор топика
server=$1
user=$2

ssh -l $2@$1 << EOF
mysqldump -u ${list_db:0} -p${list_pass:0} ${list_db:0} | gzip > $home/backup/${list_db:0}.tar.gz
EOF
anonymous
()
Ответ на: комментарий от Aborigen1020

выполняет команду на хосте, для которого указан адрес и логин

Как «хост» узнает, что во вселенной существует твоя функция, если ты эту функцию не передал в строке-команде?

Менее ресурсоемкий пример. Что будет если ты выполнишь команду в другом шелле вместо того, чтобы дергать secure shell - просто sh -c твоя_строка_команда?

anonymous
()

Без привычки заворачивать параметры в кавычки хлебнёшь ты горюшка. Те же пароли могут (и должны) содержать кучу всяких символов, которые bash может по-своему проинтерпретировать.

Впрочем, пароли в аргументах вообще плохая идея.

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

пробовал пляски с '', и eval, но результат оставался прежний. Как обходить это ограничение, кроме как в примере с EOF у анонимуса выше?

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

почему тут bash не понимает, что cmd - это функция, а усиленно передает ее как параметр к ssh?

Да, я знаю, ответ будет: «потому что ты так написал» ;-)

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

''

Внутри них не подставляются переменные. Тебе нужны ""

eval

Держись подальше от этой херни.

Как обходить это ограничение, кроме как в примере с EOF у анонимуса выше?

Заведи скрипт бекапа на машине с мускулом и дёргай его.

Но на самом деле с EOF нормальный вариант.

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

Функции - это внутренняя вещь bash. Весь остальной юникс/линукс про них знать не обязан. Для bash вызов ssh не отличается от вызова quake3, но глупо ожидать что в последний можно передать функцию на исполнение.

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

"", да, их и имел ввиду

Держись подальше от этой херни.

Чем может быть опасно? имею скрипт, в котором работает такая подстановка, вполне успешно. Однако у себя не смог применить.

Заведи скрипт бекапа на машине с мускулом и дёргай его.

Невариативно, хочу в одном скрипте делать бэкап на удаленной машине, и грузить его себе, запуская скрипт локально.

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

Хост не знает о твоем скрипте ничего - ни переменных, ни функций. Какую строку соберешь и передашь - такую и выполнит, как если бы ничего не было кроме этой строки-команды. Поэтому можешь собирать строку-команду «как в примере с EOF у анонимуса выше», можешь по другому собирать эту строку. Но главное знай, что эта строка должна быть самодостаточна. То есть строка из xtrace, которую ты выдрал в начале, должна выполняться на хосте, если его дергать отдельно от твоего скрипта.

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

Прикольно, я понял в чем мой косяк, спасибо.
глупо ожидал

Aborigen1020
() автор топика
Ответ на: комментарий от Aborigen1020
# например так, но не советую
make_cmd () {
  echo "mysqldump -u $1 -p$2 $3 | gzip > $home/backup/$1.tar.gz"
}
ssh -l $2@$1 "$(make_cmd ${list_db:0} ${list_pass:0} ${list_db:0})"
anonymous
()
Ответ на: комментарий от Aborigen1020

Тебе пока не нужны комментарии. Тебе надо самому набить шишки, чтобы понимать эти комментарии.

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

вам известны еще какие-то?

Мы передаём команды на удаленный хост в виде текста. Тут трудно придумать что-то принципиально другое. Некоторые скрипт бекапа передают в виде временного файла и уже его запускают, по моему это глупость.

Можно на ансибле сделать все то-же самое, будет более ынтырпрайзно (но если сервер всего один, то смысла 0).

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

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

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

Тут трудно придумать что-то принципиально другое

Верно, я просто думал, может я не знал про какой-то еще способ подстановки в bash, может что-то упустил из abs

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

потому что ты отвечаешь за другого пользователя

если не известны тебе, не значит, что неизвестны и другим

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

потому что ты отвечаешь за другого пользователя

Телепаты в реале.

Лучше бы набивал шишки на примерах из abs, который ты, естественно, не читал, раз задаешь такое вопросы.

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

представься, а не поясничай, анонимус))

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

#!/bin/bash
1_func () {
echo "This is one function."
}
2_func () {
echo "This is two function."
}
3_func () {
1_func
2_func
echo $1 & echo $2
}
3_func

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

Без привычки заворачивать параметры в кавычки хлебнёшь ты горюшка. Те же пароли могут (и должны) содержать кучу всяких символов, которые bash может по-своему проинтерпретировать.

Для обхода подобных костылей особенностей баша и прочих shell-языков полезно пользоваться https://www.shellcheck.net/

theNamelessOne ★★★★★
()
Последнее исправление: theNamelessOne (всего исправлений: 2)
Ответ на: комментарий от Aborigen1020

представься, а не поясничай, анонимус))

Сперва сам представься.

код ниже отрабатывает нормально(в рамках bash)

А теперь замени последнюю строку на bash -c 3_func. Нормально отработает, ведь всё в рамках bash?

Когда добьешся, чтобы отрабатывало, можешь задуматься о замене вызова bash на вызов ssh.

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

Но на самом деле с EOF нормальный вариант.

Там с $home не однозначно, впрочем, как и в оригинале вопроса.

При этом реальной нужды в eval (т.е. надобности выполнения произвольного кода пришедшего извне)

Ну хрень же, а не определение. Извне — это от (недоверенного) пользователя или по сети. Так вот, вышеотквоченный heredoc — вот это самое и есть, не вызвать скрипт, который должен быть на удаленном сервере, который проверит параметры и прочую безопасность, а именно выполнить команды, переданные в качестве командной строки по сети.

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

Извне

Извне - это значит, что на момент написания скрипта мв не знаем какие команды будем выполнять. Если бы знали - можно было бы обойтись без eval.

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

Извне - это значит, что на момент написания скрипта мв не знаем какие команды будем выполнять.

Простите, вы путаете с компилятором. Для интерпретатора:

read cmd
$cmd
и никакой eval не нужен.

Если бы знали - можно было бы обойтись без eval.

Удивительно, как тяжело человечество скрипит, когда пытается даже одну рекурсию в мозгах провернуть. Именно знание, какой набор команд и аргументов будет выполнять eval и есть залог его безопасного применения, без этого применять нельзя. Чувствуете разницу? Особенно с вышеприведенным «скриптом».

Дело в том, что не только в других shell-ах не желают добавлять конструкции, которые позволяют обойтись без eval, такие как массивы, косвенная адресация по имени переменной к переменной. Но даже в bash такие конструкции неполноценные, а если и добавляются, то по чайной ложке в пятилетку. Вот у меня куча хостов, на которых нет declare -n, потому что bash 4.2. Многомерных массивов похоже вообще не появится никогда. Является ли это проблемой? А по моему, проблема у тех, кто так и не понял, что такое eval.

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

Программирование - это управление сложностью. eval в плане привносимой сложности очень очень дорогой. Можно поторговаться, но без опыта высок шанс прогадать. Поэтому я не рекомендую eval.

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

Программирование - это управление сложностью. eval в плане привносимой сложности очень очень дорогой.

Идиосинкразия порождает кадавров. Возьмите простенькую задачу — вернуть строку из функции. На eval всё просто, быстро и безопасно, правда с одной тонкостью, но это из серии удобства и согласованности скрипта с функцией...

Но особого смысла с убеждениями спорить действительно нет, только время и нервы тратить. Ведь eval — это как с верующими учёными: «Бог есть, но так как непостижим, то мы на него не будем полагаться, обойдёмся без него». По-моему получилось именно один в один :)

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

На eval всё просто, быстро и безопасно

Я видел этот ваш возврат из функции на eval. По сути, вы модифицируете глобальное состояние. Это трюк, а не стандартный метод (которого в баше строго говоря нет).

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

Я видел этот ваш возврат из функции на eval. По сути, вы модифицируете глобальное состояние. Это трюк, а не стандартный метод

Не согласен. Этот стандартный метод носит название «возврат через глобальную переменную». На продвинутых языках этот метод зачастую означает дилетантский подход, но на *sh* — это единственный метод, когда надо вернуть что-то типа структуры или массива, там retval=$(foo) уже не только тормозит и генерирует fork, там вообще проще без функции будет. Но на sh дилетантство исчезает за счёт перекрытия области видимости. Это же и небольшое неудобство, надо всё равно следить за именами. Трюк там есть, когда функция рекурсивна.

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