【问题标题】:Run related Ubuntu commands using scala process使用 scala 进程运行相关的 Ubuntu 命令
【发布时间】:2015-09-20 17:17:30
【问题描述】:

我有一台安装了本机 Hadoop 客户端的 Ubuntu 机器,这意味着我可以运行例如:
hadoop fs -ls,只要我是某个用户,让我们说 userA。

现在我有一个 scala 应用程序在这台机器上以 root 运行(无法更改),我需要能够切换到 userA 然后运行 ​​hadoop fs -ls

我正在使用 scala.process 来运行我的命令,但我无法以它们相互连接的方式运行它们,所以如果运行:

Process(Seq("bash","-c","su userA && hadoop fs -ls")).! 我会得到一个错误,因为第二个命令实际上是在 root 上执行的,我知道这一点因为当我这样做时:
Process(Seq("bash","-c","su userA && whoami")).! 我得到 root 而不是userA

知道如何将它们联系在一起(linux 命令中的示例就足够了,我相信我可以在 scala.process 中复制它)

【问题讨论】:

    标签: linux bash scala ubuntu hadoop


    【解决方案1】:

    您的问题与 Scala、Ubuntu 或 Hadoop 本身无关。这完全是关于 shell 脚本和理解 shell 的工作方式。

    首先,您不需要调用 bash,在您的情况下,它只是另一个(不必要的)间接层。删除 bash 并留给您:

    Process("su userA && hadoop fs -ls").!
    

    ...这将失败。为什么?因为这段代码等价于:

    Process(Seq("su", "userA", "&&", "hadoop", "fs", "-ls")).!
    

    如您所见,包括&& 在内的所有命令都作为命令行参数传递给su。自然su 不知道如何处理它,因此会失败。


    现在让我们暂时忘记 Scala 代码,然后转到 bash shell 并尝试那里的命令。让我们使用whoami来测试用户是否已经变为userA

    su userA && whoami
    

    您会注意到的第一件事是su 在以这种方式调用时会提供交互式 shell 提示符(首先要求输入密码,除非您从 root 运行它)。从程序运行su 时,这可能不是您想要的。此外,在您退出该 shell 后,您会看到用户并未更改为 userA

    原因如下。 有效用户的概念与流程相关。在给定的时间点,每个进程都只有一个有效用户。进程的初始有效用户继承自生成进程。

    因此,当您从 bash 提示符运行 su userA && whoami 时会发生以下情况:

    1. bash 生成 su 作为子进程,su 从其父进程继承有效用户

      bash (root)
      +- su (root)
      
    2. su 通过setuid 更改其有效用户

      bash (root)
      +- su (userA)
      
    3. 默认情况下,su 生成指定用户的默认 shell,如在 /etc/passwd 中给出的子进程(例如 sh); sh 从其父级继承有效用户

      bash (root)
      +- su (userA)
         +- sh (userA)
      

    现在让我们进入&& 部分。它原来是 shell 语法的一部分。 command1 && command2 要求 shell 先运行 command1 然后仅在 command1 存在且没有任何错误(即其退出代码为零)运行 命令2。了解两件事至关重要:

    1. command2 仅在 command1 成功完成之后运行;
    2. command1command2 都是由同一个 shell 进程生成的,因此它们都继承了它的有效用户

    这就是我们通过su userA && whoami 调用得到的结果:

    bash (root)
    +- su (userA, already exited by the time whoami started)
    |  +- sh (userA, already exited by the time whoami started)
    +- whoami (root)
    

    因此,无论您通过su 更改为哪个用户,进程whoami 都不会受到影响。

    为了解决这个问题,您应该让whoamisu 生成,以便它可以继承更改后的用户。

    要实现这一点,请像这样调用su

    su -c whoami
    

    这将产生以下进程树:

    bash (root)
    +- su (userA)
       +- whoami (userA)
    

    现在让我们回到 Scala。不幸的是,如果你从 Scala 运行上面的命令,你会得到su: must be run from a terminal。老实说我不知道​​如何正确处理这个问题,所以我建议改用sudo

    所以最终的解决方案是:

    Process(Seq("sudo", "-u", "userA", "hadoop fs -ls")).!
    

    【讨论】:

      猜你喜欢
      • 2013-11-11
      • 1970-01-01
      • 2011-05-16
      • 2020-07-25
      • 2021-12-07
      • 1970-01-01
      • 1970-01-01
      • 2021-11-10
      • 1970-01-01
      相关资源
      最近更新 更多