91

我可以使用 shell 的组合来做到这一点,getent就像awk这样:

getent passwd $user | awk -F: '{ print $6 }'

作为参考,在 Puppet 中,我可以使用自定义事实,如下所示:

require 'etc'

Etc.passwd { |user|

   Facter.add("home_#{user.name}") do
      setcode do
         user.dir
      end
   end

}

这使得用户的主目录作为home_<user name>事实可用。

如何获取任意远程用户的主目录?

4

9 回答 9

84

Ansible(从 1.4 开始)已经在变量下为用户揭示了环境ansible_env变量。

- hosts: all
  tasks:
    - name: debug through ansible.env
      debug: var=ansible_env.HOME

不幸的是,您显然只能使用它来获取连接用户的环境变量,因为这个剧本和输出显示:

- hosts: all
  tasks:
    - name: debug specified user's home dir through ansible.env
      debug: var=ansible_env.HOME
      become: true
      become_user: "{{ user }}"

    - name: debug specified user's home dir through lookup on env
      debug: var=lookup('env','HOME')
      become: true
      become_user: "{{ user }}"

输出

vagrant@Test-01:~$ ansible-playbook -i "inventory/vagrant" env_vars.yml -e "user=testuser"

PLAY [all] ********************************************************************

GATHERING FACTS ***************************************************************
ok: [192.168.0.30]

TASK: [debug specified user's home dir through ansible.env] *******************
ok: [192.168.0.30] => {
    "var": {
        "/home/vagrant": "/home/vagrant"
    }
}

TASK: [debug specified user's home dir through lookup on env] *****************
ok: [192.168.0.30] => {
    "var": {
        "/home/vagrant": "/home/vagrant"
    }
}

PLAY RECAP ********************************************************************
192.168.0.30               : ok=3    changed=0    unreachable=0    failed=0

与Ansible中的任何内容一样,如果您无法获得一个模块来提供您想要的东西,那么您总是可以使用类似这样的东西来自由地使用(尽管应该谨慎使用,因为它可能很脆弱并且描述性较差) :

- hosts: all
  tasks:
    - name: get user home directory
      shell: >
             getent passwd {{ user }}  | awk -F: '{ print $6 }'
      changed_when: false
      register: user_home

    - name: debug output
      debug:
        var: user_home.stdout

可能有一种更清洁的方法可以做到这一点,我有点惊讶于使用become_user切换到指定的用户似乎不会影响env查找,但这应该会给你你想要的。

于 2015-10-26T10:28:42.707 回答
51

我认为这里给出了几个可行的答案,但我想我会证明你可以通过将其注册为变量来从ansible 用户模块中获取它。

- user:
    name: www-data
    state: present
  register: webserver_user_registered

注意:如果用户不存在,它将创建用户...

所以我们可以使用调试来显示该变量的值,包括路径......

- debug:
    var: webserver_user_registered

TASK [wordpress : debug] ******************
ok: [wordpresssite.org] => {
    "webserver_user_registered": {
        "append": false,
        "changed": false,
        "comment": "www-data",
        "failed": false,
        "group": 33,
        "home": "/var/www",      <<------ this is the user home dir
        "move_home": false,
        "name": "www-data",
        "shell": "/usr/sbin/nologin",
        "state": "present",
        "uid": 33
    }
}

您可以像这样在其他模块中使用这些属性;

- file:
    name: "{{ webserver_user_registered.home }}/.wp-cli"
    state: directory
于 2018-02-20T18:57:24.307 回答
31

Ansible 1.8 引入了该getent模块。它将 getent 结果注册为主机事实——在本例中,它是getent_passwd.

例子:

打印给定的主文件夹user

---

- getent:
    database: passwd
    key: "{{ user }}"
    split: ":"

- debug:
    msg: "{{ getent_passwd[user][4] }}"

累积查找表 ( user_homes),利用set_fact和 Jinja2combine()过滤器

---

- assert:
    that:
      - user_name is defined

- when: user_homes is undefined or user_name not in user_homes
  block:
    - name: getent
      become: yes
      getent:
        database: passwd
        key: "{{ user_name }}"
        split: ":"

    - name: set fact
      set_fact:
        "user_homes": "{{ user_homes | d({}) | combine({user_name: getent_passwd[user_name][4]}) }}"

不过,使用自定义事实模块会更好。

于 2017-08-01T20:51:05.543 回答
14

问题

遗憾的是,用于查找任意用户家的lookup()or ENV var 方法不能可靠地与 Ansible 一起使用,因为它以用户指定的方式运行--user=REMOTE_USER,并且可以选择使用sudo(如果sudo: yes在剧本中或--sudo通过)。这两种运行模式(sudo 或无 sudo)将改变 Ansible 在其中运行的 shell 环境,即便如此,您也将被限制为指定为-u REMOTE_USER或的用户root

您可以尝试一起使用sudo: yes, 和sudo_user: myarbitraryuser...但是由于某些版本的 Ansible中存在错误,您可能会发现它的行为不正常。如果您在 Ansible >= 上1.9,则可以使用become: true,become_user: myarbitraryuser代替。但是,这意味着您编写的剧本和角色将不适用于以前版本的 Ansible。

如果您正在寻找一种可移植的方式来获取用户的主目录,该目录也适用于 LDAP 或其他一些目录服务,请使用getent.

Ansible getent 示例

创建一个简单的剧本,名为:playbooks/ad-hoc/get-user-homedir.yml

- hosts: all
  tasks:
    - name:
      shell: >
        getent passwd {{ user }} | cut -d: -f6
      changed_when: false
      register: user_home

    - name: debug output
      debug: var=user_home.stdout

运行它:

ansible-playbook -i inventory/racktables.py playbooks/ad-hoc/get-user-homedir.yml -e "user=someuser"
于 2015-11-18T18:01:02.313 回答
4

我知道这是很老的线程,但我认为这是获取用户主目录的更简单的方法

- name: Get users homedir
  local_action: command echo ~
  register: homedir

在 Linux(或 Unix)系统上,波浪符号指向用户主目录。

于 2017-05-04T09:10:06.427 回答
3

每个答案都提到了如何在运行 playbook 并使用 debug 和 var 在屏幕上显示时打印主目录详细信息

适应@TrinitronX答案

有关将此信息用于新任务的附加信息。

我有一个需要提取其主目录的用户列表。所以我已将用户详细信息添加到列表中

- name: Get home directory
  shell: >
         getent passwd {{ item.user }} | cut -d: -f6
  changed_when: false
  with_items:
   - "{{java}}"
  register: user_home

在这里,此步骤将遍历所有用户列表并将该详细信息注册到 user_home。这将是一个数组的形式。

然后下一步是将此信息用于新任务,例如将文件采购到 bash 配置文件中。这只是一个示例,可以是任何场景,但方法将保持不变。

- name: Set Java home in .bash_profile
  lineinfile: path="{{ item.stdout }}/.bash_profile" regexp='^source "{{ java_dir }}/.bash_profile_java"' line='source "{{ java_dir }}/.bash_profile_java"' state=present
  with_items:
   - "{{ user_home.results }}"
  loop_control:
    label: "{{ item.stdout }}"

我在同一个剧本中为 java_dir 设置了一个事实 /usr/java/latest 。

数组 user_home.results 将包含获取主目录任务的详细信息。现在我们遍历这个数组并取出包含主目录路径的标准输出值。

我已将 loop_control 仅用于打印主目录,否则它将打印整个数组。

通过这个过程,我们可以确保如果有n个用户,我们可以按照这个方法,一切都会得到照顾。

注意:我已经开始学习 Ansible,如果我使用的任何术语是错误的,请原谅。我花了一些时间来弄清楚如何做到这一点并考虑分享相同的内容。

于 2018-08-27T17:33:49.753 回答
2

我来到这个线程是因为我需要从 postgres 用户打印 PGDATA env 变量,我还没有找到如何在 ansible 中更“本机”地做到这一点,但我结束了这个工作:

    - name: Find postgresql data directory
        shell: 'echo $PGDATA'
        become: yes
        become_user: postgres
        become_flags: "-i "
        register: pgdata_dir

然后我可以使用“{{ pgdata_dir.stdout }}”在另一个作业中引用它

于 2019-10-01T10:48:19.633 回答
1

目前在 Ansible 中没有简单的方法可以做到这一点,这就是为什么你应该在这个问题上添加你的投票

https://github.com/ansible/ansible/issues/15901

虽然您可以使用此解决方法:https ://stackoverflow.com/a/33343455/99834您不应该忘记发送您希望它易于使用的反馈。

于 2016-05-17T11:44:09.410 回答
0

您可以使用expanduser.

例如,在循环用户列表时:

- name: Deploys .bashrc
  template:
    src: bashrc.j2
    dest: "{{ '~' + item | expanduser }}/.bashrc"
    mode: 0640
    owner: "{{ item }}"
    group: "{{ item }}"
  with_items: user_list
于 2016-08-09T14:04:46.313 回答