Вопрос или проблема
Пишу быструю bash-функцию для изменения сетевого TTL (для раздачи интернета с телефона), но оказалось, что для каждой системы команда немного другая, поэтому, чтобы учесть логику, мой простой скрипт вырос во много строк. Вот он без несущественных частей:
#!/usr/bin/env sh
chttl(){
set -e
felicia() {
# выводит сообщения об ошибках;
}
trap 'felicia 3' INT
trap 'felicia 1' HUP QUIT ABRT TERM
chttlhelp(){
# выводит помощь, ссылку на новую копию, вики;
}
chttldo(){
if [ "$(uname)" = Darwin ]; then
sysctl net.inet.ip.ttl="${1:-65}"
elif [ "$(uname)" = Linux ] ; then
sysctl -w net.ipv4.ip_default_ttl="${1:-65}"
elif [ "$(uname)" = FreeBSD ] ; then
sysctl net.inet.ip.ttl="${1:-65}"
elif uname | grep -i "bsd"; then
# выводит некоторые указания, но ничего не делает.
else
# выводит информацию о том, почему ничего не делает.
fi
}
case "$1" in
-h|--help|-?) chttlhelp ;;
*) chttldo "$1" ;;
esac
}
chttl "$1"
Поскольку мне нужно было как-то протестировать это, я сначала превратил функцию в скрипт. И затем, поскольку я ориентируюсь на разные ОС, я решил, что было бы неплохо переключиться на sh
вместо bash
, чтобы сделать его совместимым с POSIX. Я никогда раньше не использовал bash, не знаю различий между ним и Bourne Shell, но решил, что смогу разобраться с помощью своей IDE с поддержкой ShellCheck.
И стоит отметить, что на macOS он работал нормально. На Linux (Fedora 40+) я получаю следующее:
[Fri29@18:03:16][sv@vterminal:~] $〉chttl
sysctl: permission denied on key "net.ipv4.ip_default_ttl"
[Fri29@18:03:19][sv@vterminal:~] $〉sudo chttl
sudo: chttl: command not found
[Fri29@18:03:25][sv@vterminal:~] $〉sudo -s
[Fri29@18:03:29][root@vterminal:/home/senseivita] #〉chttl
bash: chttl: command not found
Скрипт также называется chttl
, как сказано в заголовке. Он находится в ~/bin
, которая находится в моем $PATH и синхронизируется на всех системах (пути ~/{.ssh,.bash_profile,.bashrc,bin}
синхронизированы)… Ого. Неужели это оно?? (Извините, размышляю по мере написания.)
Он меняет интерпретатор, так что, возможно, ему нужен новый PATH, тоже?? PATH специфический для bash, я имею в виду… файлы имеют в себе слово “bash”. Может быть, оно наследуется случайно при переключении на sh
?? Это кажется более логичным, чем больше я об этом думаю, но я не знаю о межинтерпретаторном наследовании окружения, или как это называется. Я также понимаю, что даже не проверил, делает ли set -e
что-то в sh
, и не имею представления о том, как установить PATH для sh
вообще.
Хотя, в то же время, я вижу, что когда я повышаю свои привилегии, ошибка гласит bash: chttl: command not found
а не sh
command some-some…
Можете дать мне немного советов, пожалуйста?
ОБНОВЛЕНИЕ
Я проверил свои другие скрипты (все на bash, как я упомянул ранее) и обнаружил, что использовал то же имя для основной функции для самого скрипта и не один раз, а в куче из них, я не воображал это. Думаю, что я говорю, это что это действительно ничего не изменило, я все еще запутан (2x). “запутан плюс про макс” — звучит более эффективно.
Есть одно решение, которое, я думаю, сработает; добавление sudo
в команду sysctl
в самом скрипте, но я не думаю, что должен делать это сам, а тот, кто использует скрипт — даже если этот человек я сам. Я не разработчик, так что не знаю о надлежащем этикете скриптов. Хотя это не кажется правильным. Есть советы?
Ответ или решение
Хотите разобраться, может ли основная функция Bash-скрипта иметь то же имя, что и сам скрипт? Давайте разберемся в этом вопросе.
Проблема
В вашем сценарии вы создали функцию chttl
и скрипт с тем же именем, что может создавать определенные сложности, особенно когда вы работаете на разных операционных системах. Вопрос в том, может ли подобная организация кода приводить к ошибкам или нежелательным последствиям.
Профессиональный анализ
-
Имена функций и скриптов:
Использование одного и того же имени для функции и скрипта вbash
илиsh
допустимо и не должно приводить к проблемам само по себе. Но вы должны быть уверены, что вызываете именно нужный объект. Скрипт выполняется в отдельной среде, поэтому конфликт имен внутри одного файла обычно не возникает. -
Проблемы с правами и средой:
Сообщение об ошибкеpermission denied
указывает на то, что у вас недостаточно прав для выполнения командsysctl
, которые изменяют системные параметры. В этом случае потребуется или повысить права до root, или добавитьsudo
непосредственно перед вызовомsysctl
. Однако это решение требует осторожного подхода, так как изменение системных настроек может иметь нежелательные последствия. -
Определение интерпретатора:
Если вы наблюдаете разные поведения наmacOS
иLinux
, причина может быть в отличиях реализацииsh
иbash
. Хотя они и схожи, определенные конструкции могут работать по-разному. Убедитесь, что ваш скрипт POSIX совместим, если вы хотите, чтобы он корректно работал во всех средах. -
Переменные окружения PATH:
Если ваш скрипт находится в~/bin
, который включен в ваш$PATH
, убедитесь, что эта конфигурация применима для всех оболочек, которые вы используете (bash, sh и т.д.). Если PATH правильно настроен, черезsh
исполнение должно проходить так же, как и черезbash
. -
Конструкция с sudo:
Добавлениеsudo
непосредственно в скрипт – спорная практика. Обычно ожидается, что пользователь сам осознаёт необходимость повышения прав и выполняет команды от имени root при необходимости.
Рекомендации
-
Тестирование и отладка:
Убедитесь, что скрипт выполняется именно из нужной директории, и что PATH указывает на правильные маршруты. -
Совместимость с POSIX:
Убедитесь, что ваш код соответствует стандартам POSIX, если вы предполагаете его выполнение в средеsh
. -
Обработка прав:
Прописывайте в документации рекомендации по применению скрипта сsudo
, чтобы пользователи осознавали необходимость повышения прав.
Заключение
Дублирование имен в определенных контекстах допустимо, но требует ухода и тщательной проверки. Конфигурация среды выполнения и настройки переменных окружения играют ключевую роль в успехе. Ваша внимательность к деталям и осторожный подход к изменениям системных настроек помогут избежать ошибок и достичь работы скрипта на всех целевых системах.