Вопрос или проблема
ОС, о которой идет речь, – Fedora 40.
Я хотел бы создать директорию и скачать в нее файл, поэтому я написал этот простой скрипт
#!/bin/bash
set -eu -o pipefail
sudo -n true
test $? -eq 0 || exit 1
curlpackages="$HOME/curl-packages"
mkdir -p $curlpackages
curl --output-dir $curlpackages -JLO <someaddress>
Я ожидал, что директория и файл будут в /home/myname/
, но вместо этого я получаю /root/
. Связано ли это с тем, что я запускаю это с sudo
? Если да, могу ли я использовать другую переменную вместо $HOME
, чтобы указать на свою домашнюю папку вместо root?
Связано ли это с тем, что я запускаю это с sudo?
Да
Если да, могу ли я использовать другую переменную вместо $HOME, чтобы указать на свою домашнюю папку вместо root?
Почему бы не поместить вашу команду sudo в скрипт – только для тех команд, которые необходимо выполнять от имени root, вместо того чтобы запускать весь скрипт от имени root:
Обратите внимание, что, например, sudo echo $HOME
выведет вашу ожидаемую домашнюю директорию – потому что расширение этой переменной происходит до выполнения команды.
Вы можете использовать $SUDO_USER
SUDO_USER
Устанавливается в имя входа пользователя, который вызвал sudo.
#!/bin/bash
set -eu -o pipefail
sudo -n true
test $? -eq 0 || exit 1
userhome=$(eval echo "~$SUDO_USER")
curlpackages="$userhome/curl-packages"
mkdir -p "$curlpackages"
curl --output-dir "$curlpackages" -JLO <someaddress>
Идентификация пользователя в Bash-скрипте, вызванном с помощью sudo
Вам нужно будет указать вашего пользователя так, так как вы root:
curlpackages="/home/<yourUser>/curl-packages"
Хотя команда sudo
, которую вы имеете в своем скрипте, просто проверяет, имеет ли пользователь разрешение на использование команды sudo
.
- Вы стали root, например, с помощью:
sudo -i
илиsu
? - Если да, тогда
exit
и запустите скрипт так:sudo bash script.bash
- Тогда вам не нужно будет ничего менять
- Проверка кода выхода не требуется,
sudo -n true
не позволит скрипту выполняться пользователям без разрешений на sudo - Вы проверяете одно и то же дважды
Вот что я имею в виду, небольшое улучшение вашего кода:
#!/bin/bash
set -eu -o pipefail
sudo -n true
curlpackages="$HOME/curl-packages"
mkdir -p $curlpackages
curl --output-dir $curlpackages -JLO <someaddress>
Ответ или решение
Конечно, давайте разберем вашу ситуацию более детально.
Ваша проблема заключается в том, что при выполнении скрипта с использованием sudo
, переменная окружения $HOME
ссылается на домашний каталог пользователя root (то есть /root/
), а не на домашний каталог вашего текущего пользователя. Это поведение является нормальным при использовании sudo
, так как оно запускает команды от имени пользователя root.
Решение:
Чтобы решить эту проблему, вы можете использовать переменную окружения $SUDO_USER
, которая содержит имя пользователя, запустившего команду sudo
. Это дает вам возможность получить правильный домашний каталог для выполнения вашего скрипта.
Вот так ваш скрипт может выглядеть с использованием $SUDO_USER
:
#!/bin/bash
set -eu -o pipefail
# Проверяем, есть ли у пользователя права на sudo
sudo -n true
# Получаем домашний каталог пользователя, который запустил скрипт через sudo
userhome=$(eval echo "~$SUDO_USER")
curlpackages="$userhome/curl-packages"
mkdir -p "$curlpackages"
curl --output-dir "$curlpackages" -JLO <someaddress>
Объяснение кода:
-
Получение домашнего каталога: Используя
eval echo "~$SUDO_USER"
, мы генерируем путь к домашнему каталогу пользователя, который инициировал командуsudo
, благодаря чему у вас будет правильный каталог для загрузки файлов. -
Создание директории: После получения пути мы создаем каталог
curl-packages
в нужном месте, если он ещё не существует. -
Скачивание файла: В конце скрипта мы используем
curl
для загрузки файла в этот каталог.
Альтернативный подход:
Если вы не хотите использовать $SUDO_USER
, вы можете указать домашний каталог явно в вашем скрипте, заменив $HOME
на /home/<ваше_имя_пользователя>/
. Но использование $SUDO_USER
делает ваш скрипт более универсальным и адаптируемым для различных пользователей.
Рекомендации:
- Рассмотрите возможность запуска самого скрипта через
sudo
, без необходимостиsudo
внутри него для всех команд, если они не требуют прав администратора. - Проверка прав доступа с помощью
sudo -n true
является избыточной, поскольку, если у пользователя нет прав на использованиеsudo
, скрипт просто не выполнится.
Таким образом, предложенное решение позволяет решить проблему с неверным домашним каталогом при использовании sudo
, при этом сохраняя вашу работу организованной и понятной.