web-dev-qa-db-fra.com

Comment exécuter la commande bash avec les privilèges Sudo en Java?

J'utilise ProcessBuilder pour exécuter des commandes bash:

import Java.io.IOException;

public class Main {
    public static void main(String[] args) {
        try {
            Process pb = new ProcessBuilder("gedit").start();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

Mais je veux faire quelque chose comme ça:

Process pb = new ProcessBuilder("Sudo", "gedit").start();

Comment passer le mot de passe du superutilisateur à bash?

("gksudo", "gedit") ne fera pas l'affaire, car il a été supprimé depuis Ubuntu 13.04 et je dois le faire avec les commandes disponibles par défaut.

ÉDITER

gksudo est revenu sur Ubuntu 13.04 avec la dernière mise à jour.

24
Vare Zon

Je pense que vous pouvez l'utiliser, mais j'hésite un peu à le poster. Je vais donc simplement dire:

tilisez ceci à vos risques et périls, non recommandé, ne me poursuivez pas, etc ...

public static void main(String[] args) throws IOException {

    String[] cmd = {"/bin/bash","-c","echo password| Sudo -S ls"};
    Process pb = Runtime.getRuntime().exec(cmd);

    String line;
    BufferedReader input = new BufferedReader(new InputStreamReader(pb.getInputStream()));
    while ((line = input.readLine()) != null) {
        System.out.println(line);
    }
    input.close();
}
31
Erik Pragt

Modifiez/etc/sudoers avec visudo et accordez à votre utilisateur un droit NOPASSWD pour un script spécifique:

nom d'utilisateur ALL = (ALL) NOPASSWD: /opt/yourscript.sh

12
JointEffort

Ma solution, n'expose pas le mot de passe dans la ligne de commande, il suffit de nourrir le mot de passe dans le flux de sortie du processus. Il s'agit d'une solution plus flexible car elle vous permet de demander le mot de passe à l'utilisateur quand il est nécessaire.

public static boolean runWithPrivileges() {
    InputStreamReader input;
    OutputStreamWriter output;

    try {
        //Create the process and start it.
        Process pb = new ProcessBuilder(new String[]{"/bin/bash", "-c", "/usr/bin/Sudo -S /bin/cat /etc/sudoers 2>&1"}).start();
        output = new OutputStreamWriter(pb.getOutputStream());
        input = new InputStreamReader(pb.getInputStream());

        int bytes, tryies = 0;
        char buffer[] = new char[1024];
        while ((bytes = input.read(buffer, 0, 1024)) != -1) {
            if(bytes == 0)
                continue;
            //Output the data to console, for debug purposes
            String data = String.valueOf(buffer, 0, bytes);
            System.out.println(data);
            // Check for password request
            if (data.contains("[Sudo] password")) {
                // Here you can request the password to user using JOPtionPane or System.console().readPassword();
                // I'm just hard coding the password, but in real it's not good.
                char password[] = new char[]{'t','e','s','t'};
                output.write(password);
                output.write('\n');
                output.flush();
                // erase password data, to avoid security issues.
                Arrays.fill(password, '\0');
                tryies++;
            }
        }

        return tryies < 3;
    } catch (IOException ex) {
    }

    return false;
}
5
kato2

N'essayez pas d'écrire clairement un mot de passe système dans un fichier, en particulier pour un utilisateur qui a le privilège Sudo, tout comme @jointEffort a répondu, le privilège émis devrait être résolu par les administrateurs système et non par les rédacteurs d'applications. Sudo vous permet d'accorder des privilèges pour une commande spécifique à un utilisateur spécifique, ce qui est précisément suffisant, cochez ce message

et vous pouvez choisir de gérer le privilège dans un fichier séparé autre que le fichier sudoers principal si vous voulez simplement ajouter #includedirs /etc/sudoers.d/ en général /etc/sudoers fichier (la plupart des distributions Linux l'ont déjà fait) et créez un fichier comme ifconfig-user avec:

 USER_NAME ALL=(ALL) NOPASSWD: /sbin/ifconfig

N'oubliez pas de modifier le fichier de configuration avec visudo au cas où vous perdriez le contrôle de votre système en cas d'erreur de syntaxe.

2
armnotstrong

Une fois que vous générez un processus, vous pouvez extraire les flux d'entrée et de sortie. Introduisez simplement le mot de passe dans le flux de sortie (vous le sortez dans l'entrée du processus). Ainsi, le code ressemblerait à quelque chose -

Process pb = new ProcessBuilder("gedit").start();
OutputStream out = pb.getOutputStream();
out.write(password);
1
David Grinberg

Je sais que c'est un vieux fil mais je veux juste le mettre ici:

vous pouvez utiliser Sudo -S *command* en tant que commande que vous transmettez pour créer l'instance de processus. Ensuite, récupérez le flux de sortie et écrivez-y le mot de passe, puis ajoutez à la fin une nouvelle ligne et un c. revenir (\n\r). Le retour peut ne pas être requis mais je l'ai passé juste au cas où. C'est aussi une bonne idée de vider le flux, pour vous assurer que tout y est écrit. Je l'ai fait plusieurs fois et cela fonctionne comme un charme. Et n'oubliez pas de fermer les flux :).

1
mcrius