29

Edit Apparently, the problem was that I should have done
su - postgres -c "commands, commands, commands",
that is, passed any commands to su, rather than attempting to list them below su, because those commands (below su) aren't affected by su. /Edit

Edit 2: See David Braun's answer for an even better solution: https://stackoverflow.com/a/22947716/694469


Can I not switch user (su - postgres) in a Vagrant bootstrap shell provisioning script? (Why not?)

I'm writing such a script. In that script, I do:

echo '===== Creating PostgreSQL databases and users'

su - postgres

psql -c "
  create user SomeUserName password '...';
  alter user ...;
  "

Here, psql should attempt to login as user postgres. What happens, however, is that su - postgres apparently fails, and the shell attempts to login as user root. (Apparently, root is the user that runs the Vagrant bootstrap shell script.)

So this error appears and the psql commands aren't invoked:

psql: FATAL: role "root" does not exist

Replacing su - postgres with sudo su - postgres has no effect (I think the script is already run as root.)

I added id (which prints the current user ID) before and after su - postgres, and id prints uid=0(root) gid=0(root) groups=0(root) both before and after su was called. So as far as I can tell, su - postgres is kind of ignored? And a certain exit, later on when I attempt to switch back to the root user, exits the bootstrap script completely :-(

However. After doing vagrant ssh, I'm able to sudo su - postgres just fine, and then start psql. But not from within the provisioning script.

(A workaround is to specify -h 127.0.0.1 --username postgres when I call psql (instead of switching user to postgres). And also enable PostgreSQL trust based authentication for VM local connections.)

4

4 回答 4

24
echo '===== Creating PostgreSQL databases and users'

su postgres << EOF
psql -c "
  create user SomeUserName password '...';
  alter user ...;
  "
EOF
于 2014-04-08T20:40:32.753 回答
14

我只是在寻找一种以非 root 身份运行 Vagrant 提供程序脚本的方法时发现了这一点,并且想为观察到的行为添加一个解释,这是非常基础的 Unix 知识,对读者来说很有用。

在 shell 脚本中运行程序(例如 /bin/sh、sudo 或 su)不能更改它运行的上下文(工作目录、运行用户等)中的任何内容,只能为其创建的进程设置上下文(并且仅如果以 root 身份运行,请更改正在运行的 uid - uid 0)。这也是为什么 cd 是 shell 中的内置命令的原因。su 是一个 setuid 程序(当您尝试命令“ls -l”时请注意“s” which su),这意味着它将作为拥有该程序的用户(root)而不是作为运行它的用户运行。

于 2013-10-16T13:23:47.680 回答
10

LHP 是对的:这并不是一个真正的流浪问题。前段时间我需要这样做,这就是我解决它的方法:

#!/bin/bash

case $(id -u) in
    0) 
         echo first: running as root
         echo doing the root tasks...
         sudo -u vagrant -i $0  # script calling itself as the vagrant user
         ;;
    *) 
         echo then: running as vagrant user
         echo doing the vagrant user's tasks
         ;;
esac

也许这可能对某人有用,但另一个明显的解决方案是使用 sudo 运行第二个脚本。

已修复:谢谢 Macattack。我直接在stackoverflow中写了,它仍然没有测试。

编辑:这个问题已经过编辑,现在它的描述和大多数答案都集中在“如何使用正确的用户创建 postgres 数据库”而不是如何在 vagrant 脚本中切换用户。

于 2014-02-24T10:32:47.553 回答
3

我不确定您是否可以在 Vagrant shell 脚本中切换用户,因为这可能需要用户输入,而当脚本在配置程序中运行时您无法提供它......但为什么不直接使用 psql 命令指定用户呢?

psql --username=postgres -c "..."
于 2013-05-27T12:54:38.967 回答