diff --git a/.gitea/workflows/release.yaml b/.gitea/workflows/release.yaml index d995bcb..6a775ff 100644 --- a/.gitea/workflows/release.yaml +++ b/.gitea/workflows/release.yaml @@ -85,11 +85,18 @@ jobs: sed -i "s/release='[0-9]\+'/release='1'/g" alr-default/alr-bin/alr.sh - name: Install alr + env: + CREATE_SYSTEM_RESOURCES: 0 run: | - groupadd wheel - usermod -aG wheel root make install + - name: Prepare directories for ALR + run: | + # Создаём необходимые директории для работы alr build + mkdir -p /tmp/alr/dl /tmp/alr/pkgs /var/cache/alr + chmod -R 777 /tmp/alr + chmod -R 755 /var/cache/alr + - name: Build packages run: | SCRIPT_PATH=alr-default/alr-bin/alr.sh diff --git a/fix.go b/fix.go index 3872d18..b89a070 100644 --- a/fix.go +++ b/fix.go @@ -34,6 +34,21 @@ import ( "gitea.plemya-x.ru/Plemya-x/ALR/internal/utils" ) +// execWithPrivileges выполняет команду напрямую если root или CI, иначе через sudo +func execWithPrivileges(name string, args ...string) *exec.Cmd { + isRoot := os.Geteuid() == 0 + isCI := os.Getenv("CI") == "true" + + if !isRoot && !isCI { + // Если не root и не в CI, используем sudo + allArgs := append([]string{name}, args...) + return exec.Command("sudo", allArgs...) + } else { + // Если root или в CI, запускаем напрямую + return exec.Command(name, args...) + } +} + func FixCmd() *cli.Command { return &cli.Command{ Name: "fix", @@ -90,7 +105,7 @@ func FixCmd() *cli.Command { // Если не получилось удалить, пробуем через sudo slog.Warn(gotext.Get("Unable to remove cache item (%s) as current user, trying with sudo", entry)) - sudoCmd := exec.Command("sudo", "rm", "-rf", fullPath) + sudoCmd := execWithPrivileges("rm", "-rf", fullPath) if sudoErr := sudoCmd.Run(); sudoErr != nil { // Если и через sudo не получилось, пропускаем с предупреждением slog.Error(gotext.Get("Unable to remove cache item (%s)", entry), "error", err) @@ -109,7 +124,7 @@ func FixCmd() *cli.Command { if err != nil { // Если не получилось удалить, пробуем через sudo slog.Warn(gotext.Get("Unable to remove temporary directory as current user, trying with sudo")) - sudoCmd := exec.Command("sudo", "rm", "-rf", tmpDir) + sudoCmd := execWithPrivileges("rm", "-rf", tmpDir) if sudoErr := sudoCmd.Run(); sudoErr != nil { slog.Error(gotext.Get("Unable to remove temporary directory"), "error", err) } @@ -143,12 +158,12 @@ func FixCmd() *cli.Command { // Проверяем, есть ли файлы в директории entries, err := os.ReadDir(tmpDir) if err == nil && len(entries) > 0 { - fixCmd := exec.Command("sudo", "chown", "-R", "root:wheel", tmpDir) + fixCmd := execWithPrivileges("chown", "-R", "root:wheel", tmpDir) if fixErr := fixCmd.Run(); fixErr != nil { slog.Warn(gotext.Get("Unable to fix file ownership"), "error", fixErr) } - fixCmd = exec.Command("sudo", "chmod", "-R", "2775", tmpDir) + fixCmd = execWithPrivileges("chmod", "-R", "2775", tmpDir) if fixErr := fixCmd.Run(); fixErr != nil { slog.Warn(gotext.Get("Unable to fix file permissions"), "error", fixErr) } @@ -162,18 +177,18 @@ func FixCmd() *cli.Command { if err != nil { // Если не получилось, пробуем через sudo с правильными правами для группы wheel slog.Info(gotext.Get("Creating cache directory with sudo")) - sudoCmd := exec.Command("sudo", "mkdir", "-p", paths.CacheDir) + sudoCmd := execWithPrivileges("mkdir", "-p", paths.CacheDir) if sudoErr := sudoCmd.Run(); sudoErr != nil { return cliutils.FormatCliExit(gotext.Get("Unable to create new cache directory"), err) } // Устанавливаем права 775 и группу wheel - chmodCmd := exec.Command("sudo", "chmod", "775", paths.CacheDir) + chmodCmd := execWithPrivileges("chmod", "775", paths.CacheDir) if chmodErr := chmodCmd.Run(); chmodErr != nil { return cliutils.FormatCliExit(gotext.Get("Unable to set cache directory permissions"), chmodErr) } - chgrpCmd := exec.Command("sudo", "chgrp", "wheel", paths.CacheDir) + chgrpCmd := execWithPrivileges("chgrp", "wheel", paths.CacheDir) if chgrpErr := chgrpCmd.Run(); chgrpErr != nil { return cliutils.FormatCliExit(gotext.Get("Unable to set cache directory group"), chgrpErr) } diff --git a/internal/manager/common.go b/internal/manager/common.go index 362f0e0..38a997e 100644 --- a/internal/manager/common.go +++ b/internal/manager/common.go @@ -16,14 +16,30 @@ package manager -import "os/exec" +import ( + "os" + "os/exec" +) type CommonPackageManager struct { noConfirmArg string } func (m *CommonPackageManager) getCmd(opts *Opts, mgrCmd string, args ...string) *exec.Cmd { - cmd := exec.Command(mgrCmd) + var cmd *exec.Cmd + + // Проверяем, нужно ли повышение привилегий + isRoot := os.Geteuid() == 0 + isCI := os.Getenv("CI") == "true" + + if !isRoot && !isCI { + // Если не root и не в CI, используем sudo + cmd = exec.Command("sudo", mgrCmd) + } else { + // Если root или в CI, запускаем напрямую + cmd = exec.Command(mgrCmd) + } + cmd.Args = append(cmd.Args, opts.Args...) cmd.Args = append(cmd.Args, args...) diff --git a/internal/utils/utils.go b/internal/utils/utils.go index f78e09c..fe36e6c 100644 --- a/internal/utils/utils.go +++ b/internal/utils/utils.go @@ -39,19 +39,45 @@ func EnsureTempDirWithRootOwner(path string, mode os.FileMode) error { return err } - // Все каталоги в /tmp/alr доступны для группы wheel - // Устанавливаем setgid бит (2775), чтобы новые файлы наследовали группу + // В CI или если мы уже root, не нужно использовать sudo + isRoot := os.Geteuid() == 0 + isCI := os.Getenv("CI") == "true" + + // Если мы в CI или root, выполняем команды напрямую + // В противном случае используем sudo permissions := "2775" group := "wheel" + var chmodCmd, chownCmd *exec.Cmd + if isRoot || isCI { + // Выполняем команды напрямую без sudo + chmodCmd = exec.Command("chmod", permissions, path) + chownCmd = exec.Command("chown", "root:"+group, path) + } else { + // Используем sudo для обычных пользователей + chmodCmd = exec.Command("sudo", "chmod", permissions, path) + chownCmd = exec.Command("sudo", "chown", "root:"+group, path) + } + // Устанавливаем права с setgid битом - err = exec.Command("sudo", "chmod", permissions, path).Run() + err = chmodCmd.Run() if err != nil { - return err + // В CI или для root игнорируем ошибки, если группа wheel не существует + if !isRoot && !isCI { + return err + } } // Устанавливаем владельца root:wheel - return exec.Command("sudo", "chown", "root:"+group, path).Run() + err = chownCmd.Run() + if err != nil { + // В CI или для root игнорируем ошибки, если группа wheel не существует + if !isRoot && !isCI { + return err + } + } + + return nil } // Для остальных каталогов обычное создание diff --git a/scripts/install.sh b/scripts/install.sh index dc54478..5ade7b2 100755 --- a/scripts/install.sh +++ b/scripts/install.sh @@ -32,12 +32,20 @@ error() { installPkg() { rootCmd="" - if command -v doas &>/dev/null; then - rootCmd="doas" - elif command -v sudo &>/dev/null; then - rootCmd="sudo" + + # Проверяем, запущен ли скрипт от root + if [ "$(id -u)" = "0" ]; then + # Если root, не используем sudo/doas + rootCmd="" else - warn "Не обнаружена команда повышения привилегий (например, sudo, doas)" + # Если не root, ищем команду повышения привилегий + if command -v doas &>/dev/null; then + rootCmd="doas" + elif command -v sudo &>/dev/null; then + rootCmd="sudo" + else + warn "Не обнаружена команда повышения привилегий (например, sudo, doas)" + fi fi case $1 in