如何在bash脚本中获得不同用户的主目录?

时间:2022-06-25 15:43:15

I need to execute part of a bash script as a different user, and inside that user's $HOME directory. However, I'm not sure how to determine this variable. Switching to that user and calling $HOME does not provide the correct location:

我需要作为一个不同的用户执行bash脚本的一部分,并在该用户的$HOME目录中执行。但是,我不确定如何确定这个变量。切换到该用户并调用$HOME并没有提供正确的位置:

# running script as root, but switching to a different user...
su - $different_user
echo $HOME
# returns /root/ but should be /home/myuser

Update:

It appears that the issue is with the way that I am trying to switch users in my script:

似乎问题在于我试图在我的脚本中切换用户的方式:

$different_user=deploy

# create user
useradd -m -s /bin/bash $different_user

echo "Current user: `whoami`"
# Current user: root

echo "Switching user to $different_user"
# Switching user to deploy

su - $different_user
echo "Current user: `whoami`"
# Current user: root
echo "Current user: `id`"
# Current user: uid=0(root) gid=0(root) groups=0(root)

sudo su $different_user
# Current user: root
# Current user: uid=0(root) gid=0(root) groups=0(root)

What is the correct way to switch users and execute commands as a different user in a bash script?

在bash脚本中,切换用户和执行命令的正确方式是什么?

10 个解决方案

#1


71  

Update: Based on this question's title, people seem to come here just looking for a way to find a different user's home directory, without the need to impersonate that user.

更新:基于这个问题的标题,人们似乎来到这里只是寻找一种方法来找到一个不同的用户的主目录,而不需要模仿那个用户。

In that case, the simplest solution is to use tilde expansion with the username of interest, combined with eval (which is needed, because the username must be given as an unquoted literal in order for tilde expansion to work):

在这种情况下,最简单的解决方案是使用带有感兴趣的用户名的tilde扩展,并结合eval(这是必需的,因为用户名必须作为一个非引用的文字,以使tilde展开工作):

eval echo "~$different_user"    # prints $different_user's home dir.

Note: The usual caveats regarding the use of eval apply; in this case, the assumption is that you control the value of $different_user and know it to be a mere username.

注:关于使用eval应用的常见警告;在这种情况下,假设您控制$不同的用户的值,并且知道它只是一个用户名。

By contrast, the remainder of this answer deals with impersonating a user and performing operations in that user's home directory.

与此相反,此答案的其余部分处理在该用户的主目录中模拟用户和执行操作。


Note:

注意:

  • Administrators by default and other users if authorized via the sudoers file can impersonate other users via sudo.
  • 默认情况下,管理员和其他用户如果通过sudoers文件授权,可以通过sudo模拟其他用户。
  • The following is based on the default configuration of sudo - changing its configuration can make it behave differently - see man sudoers.
  • 以下是基于sudo的默认配置——更改其配置可以使其行为不同——见人sudoers。

The basic form of executing a command as another user is:

作为另一个用户执行命令的基本形式是:

sudo -H -u someUser someExe [arg1 ...]
  # Example:
sudo -H -u root env  # print the root user's environment

Note:

注意:

  • If you neglect to specify -H, the impersonating process (the process invoked in the context of the specified user) will report the original user's home directory in $HOME.
  • 如果忽略指定-H,模拟过程(在指定用户的上下文中调用的流程)将在$ home中报告原始用户的主目录。
  • The impersonating process will have the same working directory as the invoking process.
  • 模拟过程将具有与调用过程相同的工作目录。
  • The impersonating process performs no shell expansions on string literals passed as arguments, since no shell is involved in the impersonating process (unless someExe happens to be a shell) - expansions by the invoking shell - prior to passing to the impersonating process - can obviously still occur.
  • 模拟过程不执行作为参数传递的字符串文本的shell扩展,因为在模拟过程中没有任何shell(除非某些exe碰巧是shell)——在传递到模拟过程之前,调用shell的扩展——显然仍然会发生。

Optionally, you can have an impersonating process run as or via a(n impersonating) shell, by prefixing someExe either with -i or -s - not specifying someExe ... creates an interactive shell:

可选地,您可以通过一个(n模拟)shell来运行一个模拟过程,通过对某些exe进行前缀- - -或-s -,而不是指定某个exe…创建一个交互式shell:

  • -i creates a login shell for someUser, which implies the following:

    -我为someUser创建了一个login shell,它包含以下内容:

    • someUser's user-specific shell profile, if defined, is loaded.
    • someUser的特定于用户的shell概要文件(如果定义了)将被加载。
    • $HOME points to someUser's home directory, so there's no need for -H (though you may still specify it)
    • $HOME指向某个用户的主目录,因此不需要-H(尽管您仍然可以指定它)
    • The working directory for the impersonating shell is the someUser's home directory.
    • 模拟shell的工作目录是someUser的主目录。
  • -s creates a non-login shell:

    -s创建一个非登录shell:

    • no shell profile is loaded (though initialization files for interactive nonlogin shells are; e.g., ~/.bashrc)
    • 没有加载shell概要文件(尽管交互式非登录shell的初始化文件是;例如,~ / . bashrc)
    • Unless you also specify -H, the impersonating process will report the original user's home directory in $HOME.
    • 除非您还指定-H,否则模拟过程将报告原始用户的主目录在$ home中。
    • The impersonating shell will have the same working directory as the invoking process.
    • 模拟shell将具有与调用过程相同的工作目录。

Using a shell means that string arguments passed on the command line MAY be subject to shell expansions - see platform-specific differences below - by the impersonating shell (possibly after initial expansion by the invoking shell); compare the the following two commands (which use single quotes to prevent premature expansion by the invoking shell):

使用shell意味着在命令行上传递的字符串参数可能会受到shell扩展的影响——请参见下面的特定于平台的差异——通过模拟shell(可能是在调用shell初始扩展之后);比较以下两个命令(使用单引号防止调用shell提前扩展):

  # Run root's shell profile, change to root's home dir.
sudo -u root -i eval 'echo $SHELL - $USER - $HOME - $PWD'
  # Don't run root's shell profile, use current working dir.
  # Note the required -H to define $HOME as root`s home dir.
sudo -u root -H -s eval 'echo $SHELL - $USER - $HOME - $PWD'

What shell is invoked is determined by "the SHELL environment variable if it is set or the shell as specified in passwd(5)" (according to man sudo). Note that with -s it is the invoking user's environment that matters, whereas with -i it is the impersonated user's.

shell所调用的是由“shell环境变量,如果它是设置的,或者是在passwd(5)中指定的shell”所决定的。(根据sudo)人。注意,在-s中,它是调用用户的环境,而我是模拟用户。

Note that there are platform differences regarding shell-related behavior (with -i or -s):

请注意,关于与shell相关的行为,有平台上的差异(i或-s):

  • sudo on Linux apparently only accepts an executable or builtin name as the first argument following -s/-i, whereas OSX allows passing an entire shell command line; e.g., OSX accepts sudo -u root -s 'echo $SHELL - $USER - $HOME - $PWD' directly (no need for eval), whereas Linux doesn't (as of sudo 1.8.95p).

    在Linux上,sudo显然只接受一个可执行文件或builtin名称作为第一个参数——s/-i,而OSX允许传递整个shell命令行;例如,OSX接受sudo -u root -s 'echo $SHELL - $USER - $HOME - $PWD'直接(不需要eval),而Linux则没有(sudo 1.8.95p)。

  • Older versions of sudo on Linux do NOT apply shell expansions to arguments passed to a shell; for instance, with sudo 1.8.3p1 (e.g., Ubuntu 12.04), sudo -u root -H -s echo '$HOME' simply echoes the string literal "$HOME" instead of expanding the variable reference in the context of the root user. As of at least sudo 1.8.9p5 (e.g., Ubuntu 14.04) this has been fixed. Therefore, to ensure expansion on Linux even with older sudo versions, pass the the entire command as a single argument to eval; e.g.: sudo -u root -H -s eval 'echo $HOME'. (Although not necessary on OSX, this will work there, too.)

    在Linux上的旧版本的sudo不应用shell扩展来将参数传递给shell;例如,sudo 1.8.3p1(例如Ubuntu 12.04), sudo -u root -H -s echo“$HOME”只是简单地响应字符串字面“$HOME”,而不是在根用户的上下文中扩展变量引用。至少sudo 1.8.9p5(例如Ubuntu 14.04)已经被修复了。因此,为了确保在更大的sudo版本中对Linux进行扩展,将整个命令作为一个参数传递给eval;例:sudo -u root -H -s eval 'echo $HOME'。(虽然在OSX上没有必要,但这也会在那里工作。)

  • The root user's $SHELL variable contains /bin/sh on OSX 10.9, whereas it is /bin/bash on Ubuntu 12.04.

    根用户的$SHELL变量包含/bin/sh在osx10.9上,而在Ubuntu 12.04上是/bin/bash。

Whether the impersonating process involves a shell or not, its environment will have the following variables set, reflecting the invoking user and command: SUDO_COMMAND, SUDO_USER, SUDO_UID=, SUDO_GID.

无论模拟过程是否涉及shell,它的环境都有以下变量集,反映调用用户和命令:SUDO_COMMAND、SUDO_USER、SUDO_UID=、SUDO_GID。

See man sudo and man sudoers for many more subtleties.

看看男人的sudo和人类的sudoers,就会发现更多的微妙之处。

Tip of the hat to @DavidW and @Andrew for inspiration.

向@DavidW和@Andrew致敬。

#2


20  

In BASH, you can find a user's $HOME directory by prefixing the user's login ID with a tilde character. For example:

在BASH中,您可以通过使用一个tilde字符预先设置用户的登录ID来找到用户的$HOME目录。例如:

$ echo ~bob

This will echo out user bob's $HOME directory.

这将响应用户bob的$HOME目录。

However, you say you want to be able to execute a script as a particular user. To do that, you need to setup sudo. This command allows you to execute particular commands as either a particular user. For example, to execute foo as user bob:

但是,您说您希望能够作为特定用户执行脚本。要做到这一点,您需要设置sudo。这个命令允许您作为特定的用户执行特定的命令。例如,要执行foo作为用户bob:

$ sudo -i -ubob -sfoo

This will start up a new shell, and the -i will simulate a login with the user's default environment and shell (which means the foo command will execute from the bob's$HOME` directory.)

这将启动一个新的shell,并且-i将模拟用户的默认环境和shell的登录(这意味着foo命令将从bob的$HOME目录执行)。

Sudo is a bit complex to setup, and you need to be a superuser just to be able to see the shudders file (usually /etc/sudoers). However, this file usually has several examples you can use.

Sudo是一个有点复杂的设置,您需要成为一个超级用户才能够看到shuader文件(通常是/etc/sudoers)。但是,这个文件通常有几个您可以使用的例子。

In this file, you can specify the commands you specify who can run a command, as which user, and whether or not that user has to enter their password before executing that command. This is normally the default (because it proves that this is the user and not someone who came by while the user was getting a Coke.) However, when you run a shell script, you usually want to disable this feature.

在这个文件中,您可以指定您指定谁可以运行一个命令,哪个用户,以及该用户在执行该命令之前是否必须输入密码。这通常是默认的(因为它证明了这是用户,而不是用户得到可乐的时候来的人)。但是,当您运行shell脚本时,通常希望禁用该特性。

#3


12  

For the sake of an alternative answer for those searching for a lightweight way to just find a user's home dir...

为了找到一个替代的答案,寻找一个轻量级的方法来找到一个用户的主目录…

Rather than messing with su hacks, or bothering with the overhead of launching another bash shell just to find the $HOME environment variable...

而不是干扰su的黑客,或者为了找到$HOME环境变量而麻烦启动另一个bash shell的开销……

Lightweight Simple Homedir Query via Bash

There is a command specifically for this: getent

有一个专门针对这个的命令:getent。

getent passwd someuser | cut -f6 -d:

getent passwd someuser | cut -f6 -d:

getent can do a lot more... just see the man page. The passwd nsswitch database will return the user's entry in /etc/passwd format. Just split it on the colon : to parse out the fields.

getent可以做更多的事情…只要看看这个人的页面。passwd nsswitch数据库将返回用户的/etc/passwd格式的条目。将其拆分为冒号:解析字段。

It should be installed on most Linux systems (or any system that uses GNU Lib C (RHEL: glibc-common, Deb: libc-bin)

它应该安装在大多数Linux系统上(或者任何使用GNU Lib C的系统(RHEL: glibc-common, Deb: libc-bin)

#4


3  

You want the -u option for sudo in this case. From the man page:

在这种情况下,你需要sudo的-u选项。从手册页:

The -u (user) option causes sudo to run the specified command as a user other than root.

If you don't need to actually run it as them, you could move to their home directory with ~<user>. As in, to move into my home directory you would use cd ~chooban.

如果您不需要实际运行它,您可以使用~ 来移动到它们的主目录。如进入我的家庭目录,你将使用cd ~chooban。

#5


1  

So you want to:

所以你想:

  1. execute part of a bash script as a different user
  2. 作为不同的用户执行bash脚本的一部分。
  3. change to that user's $HOME directory
  4. 更改为该用户的$HOME目录。

Inspired by this answer, here's the adapted version of your script:

受这个答案的启发,下面是你的剧本的改编版本:

#!/usr/bin/env bash

different_user=deploy

useradd -m -s /bin/bash "$different_user"

echo "Current user: $(whoami)"
echo "Current directory: $(pwd)"
echo

echo "Switching user to $different_user"
sudo -u "$different_user" -i /bin/bash - <<-'EOF'
    echo "Current user: $(id)"
    echo "Current directory: $(pwd)"
EOF
echo

echo "Switched back to $(whoami)"

different_user_home="$(eval echo ~"$different_user")"
echo "$different_user home directory: $different_user_home"

When you run it, you should get the following:

当你运行它时,你应该得到以下信息:

Current user: root
Current directory: /root

Switching user to deploy
Current user: uid=1003(deploy) gid=1003(deploy) groups=1003(deploy)
Current directory: /home/deploy

Switched back to root
deploy home directory: /home/deploy

#6


1  

I was also looking for this, but didn't want to impersonate a user to simply acquire a path!

我也在寻找这个,但是不想模仿用户简单地获取一条路径!

user_path=$(grep $username /etc/passwd|cut -f6 -d":");

user_path=$(grep $username /etc/passwd|cut -f6 -d“:”);

Now in your script, you can refer to $user_path in most cases would be /home/username

现在,在您的脚本中,您可以在大多数情况下引用$user_path作为/home/username。

Assumes: You have previously set $username with the value of the intended users username. Source: http://www.unix.com/shell-programming-and-scripting/171782-cut-fields-etc-passwd-file-into-variables.html

假设:您之前设置了$username,其值为预期用户名。来源:http://www.unix.com/shell-programming-and-scripting/171782-cut-fields-etc-passwd-file-into-variables.html

#7


1  

This works in Linux. Not sure how it behaves in other *nixes.

这是在Linux中。不确定它在其他*nix中的表现。

  getent passwd "${OTHER_USER}"|cut -d\: -f 6

#8


0  

Quick and dirty, and store it in a variable:

又快又脏,把它存储在一个变量中:

USER=somebody
USER_HOME="$(echo -n $(bash -c "cd ~${USER} && pwd"))"

#9


0  

I was struggling with this question because I was looking for a way to do this in a bash script for OS X, hence /etc/passwd was out of the question, and my script was meant to be executed as root, therefore making the solutions invoking eval or bash -c dangerous as they allowed code injection into the variable specifying the username.

我很困扰这个问题,因为我正在寻找一个方法在OS X的bash脚本,因此/ etc / passwd的问题,和我的脚本是作为根用户执行,因此使解决方案调用eval或bash - c危险,因为他们允许代码注入变量指定用户名。

Here is what I found. It's simple and doesn't put a variable inside a subshell. However it does require the script to be ran by root as it sudos into the specified user account.

这是我的发现。它很简单,并没有在子shell中放入一个变量。但是,它确实要求脚本在sudos进入指定用户帐户时由根运行。

Presuming that $SOMEUSER contains a valid username:

假设$SOMEUSER包含一个有效的用户名:

echo "$(sudo -H -u "$SOMEUSER" -s -- "cd ~ && pwd")"

I hope this helps somebody!

我希望这能帮助别人!

#10


0  

If the user doesn't exist, getent will return an error.

如果用户不存在,getent将返回一个错误。

Here's a small shell function that doesn't ignore the exit code of getent:

下面是一个小的shell函数,它不会忽略getent的退出代码:

get_home() {
  local result; result="$(getent passwd "$1")" || return
  echo $result | cut -d : -f 6
}

Here's a usage example:

这里有一个使用的例子:

da_home="$(get_home missing_user)" || {
  echo 'User does NOT exist!'; exit 1
}

# Now do something with $da_home
echo "Home directory is: '$da_home'"

#1


71  

Update: Based on this question's title, people seem to come here just looking for a way to find a different user's home directory, without the need to impersonate that user.

更新:基于这个问题的标题,人们似乎来到这里只是寻找一种方法来找到一个不同的用户的主目录,而不需要模仿那个用户。

In that case, the simplest solution is to use tilde expansion with the username of interest, combined with eval (which is needed, because the username must be given as an unquoted literal in order for tilde expansion to work):

在这种情况下,最简单的解决方案是使用带有感兴趣的用户名的tilde扩展,并结合eval(这是必需的,因为用户名必须作为一个非引用的文字,以使tilde展开工作):

eval echo "~$different_user"    # prints $different_user's home dir.

Note: The usual caveats regarding the use of eval apply; in this case, the assumption is that you control the value of $different_user and know it to be a mere username.

注:关于使用eval应用的常见警告;在这种情况下,假设您控制$不同的用户的值,并且知道它只是一个用户名。

By contrast, the remainder of this answer deals with impersonating a user and performing operations in that user's home directory.

与此相反,此答案的其余部分处理在该用户的主目录中模拟用户和执行操作。


Note:

注意:

  • Administrators by default and other users if authorized via the sudoers file can impersonate other users via sudo.
  • 默认情况下,管理员和其他用户如果通过sudoers文件授权,可以通过sudo模拟其他用户。
  • The following is based on the default configuration of sudo - changing its configuration can make it behave differently - see man sudoers.
  • 以下是基于sudo的默认配置——更改其配置可以使其行为不同——见人sudoers。

The basic form of executing a command as another user is:

作为另一个用户执行命令的基本形式是:

sudo -H -u someUser someExe [arg1 ...]
  # Example:
sudo -H -u root env  # print the root user's environment

Note:

注意:

  • If you neglect to specify -H, the impersonating process (the process invoked in the context of the specified user) will report the original user's home directory in $HOME.
  • 如果忽略指定-H,模拟过程(在指定用户的上下文中调用的流程)将在$ home中报告原始用户的主目录。
  • The impersonating process will have the same working directory as the invoking process.
  • 模拟过程将具有与调用过程相同的工作目录。
  • The impersonating process performs no shell expansions on string literals passed as arguments, since no shell is involved in the impersonating process (unless someExe happens to be a shell) - expansions by the invoking shell - prior to passing to the impersonating process - can obviously still occur.
  • 模拟过程不执行作为参数传递的字符串文本的shell扩展,因为在模拟过程中没有任何shell(除非某些exe碰巧是shell)——在传递到模拟过程之前,调用shell的扩展——显然仍然会发生。

Optionally, you can have an impersonating process run as or via a(n impersonating) shell, by prefixing someExe either with -i or -s - not specifying someExe ... creates an interactive shell:

可选地,您可以通过一个(n模拟)shell来运行一个模拟过程,通过对某些exe进行前缀- - -或-s -,而不是指定某个exe…创建一个交互式shell:

  • -i creates a login shell for someUser, which implies the following:

    -我为someUser创建了一个login shell,它包含以下内容:

    • someUser's user-specific shell profile, if defined, is loaded.
    • someUser的特定于用户的shell概要文件(如果定义了)将被加载。
    • $HOME points to someUser's home directory, so there's no need for -H (though you may still specify it)
    • $HOME指向某个用户的主目录,因此不需要-H(尽管您仍然可以指定它)
    • The working directory for the impersonating shell is the someUser's home directory.
    • 模拟shell的工作目录是someUser的主目录。
  • -s creates a non-login shell:

    -s创建一个非登录shell:

    • no shell profile is loaded (though initialization files for interactive nonlogin shells are; e.g., ~/.bashrc)
    • 没有加载shell概要文件(尽管交互式非登录shell的初始化文件是;例如,~ / . bashrc)
    • Unless you also specify -H, the impersonating process will report the original user's home directory in $HOME.
    • 除非您还指定-H,否则模拟过程将报告原始用户的主目录在$ home中。
    • The impersonating shell will have the same working directory as the invoking process.
    • 模拟shell将具有与调用过程相同的工作目录。

Using a shell means that string arguments passed on the command line MAY be subject to shell expansions - see platform-specific differences below - by the impersonating shell (possibly after initial expansion by the invoking shell); compare the the following two commands (which use single quotes to prevent premature expansion by the invoking shell):

使用shell意味着在命令行上传递的字符串参数可能会受到shell扩展的影响——请参见下面的特定于平台的差异——通过模拟shell(可能是在调用shell初始扩展之后);比较以下两个命令(使用单引号防止调用shell提前扩展):

  # Run root's shell profile, change to root's home dir.
sudo -u root -i eval 'echo $SHELL - $USER - $HOME - $PWD'
  # Don't run root's shell profile, use current working dir.
  # Note the required -H to define $HOME as root`s home dir.
sudo -u root -H -s eval 'echo $SHELL - $USER - $HOME - $PWD'

What shell is invoked is determined by "the SHELL environment variable if it is set or the shell as specified in passwd(5)" (according to man sudo). Note that with -s it is the invoking user's environment that matters, whereas with -i it is the impersonated user's.

shell所调用的是由“shell环境变量,如果它是设置的,或者是在passwd(5)中指定的shell”所决定的。(根据sudo)人。注意,在-s中,它是调用用户的环境,而我是模拟用户。

Note that there are platform differences regarding shell-related behavior (with -i or -s):

请注意,关于与shell相关的行为,有平台上的差异(i或-s):

  • sudo on Linux apparently only accepts an executable or builtin name as the first argument following -s/-i, whereas OSX allows passing an entire shell command line; e.g., OSX accepts sudo -u root -s 'echo $SHELL - $USER - $HOME - $PWD' directly (no need for eval), whereas Linux doesn't (as of sudo 1.8.95p).

    在Linux上,sudo显然只接受一个可执行文件或builtin名称作为第一个参数——s/-i,而OSX允许传递整个shell命令行;例如,OSX接受sudo -u root -s 'echo $SHELL - $USER - $HOME - $PWD'直接(不需要eval),而Linux则没有(sudo 1.8.95p)。

  • Older versions of sudo on Linux do NOT apply shell expansions to arguments passed to a shell; for instance, with sudo 1.8.3p1 (e.g., Ubuntu 12.04), sudo -u root -H -s echo '$HOME' simply echoes the string literal "$HOME" instead of expanding the variable reference in the context of the root user. As of at least sudo 1.8.9p5 (e.g., Ubuntu 14.04) this has been fixed. Therefore, to ensure expansion on Linux even with older sudo versions, pass the the entire command as a single argument to eval; e.g.: sudo -u root -H -s eval 'echo $HOME'. (Although not necessary on OSX, this will work there, too.)

    在Linux上的旧版本的sudo不应用shell扩展来将参数传递给shell;例如,sudo 1.8.3p1(例如Ubuntu 12.04), sudo -u root -H -s echo“$HOME”只是简单地响应字符串字面“$HOME”,而不是在根用户的上下文中扩展变量引用。至少sudo 1.8.9p5(例如Ubuntu 14.04)已经被修复了。因此,为了确保在更大的sudo版本中对Linux进行扩展,将整个命令作为一个参数传递给eval;例:sudo -u root -H -s eval 'echo $HOME'。(虽然在OSX上没有必要,但这也会在那里工作。)

  • The root user's $SHELL variable contains /bin/sh on OSX 10.9, whereas it is /bin/bash on Ubuntu 12.04.

    根用户的$SHELL变量包含/bin/sh在osx10.9上,而在Ubuntu 12.04上是/bin/bash。

Whether the impersonating process involves a shell or not, its environment will have the following variables set, reflecting the invoking user and command: SUDO_COMMAND, SUDO_USER, SUDO_UID=, SUDO_GID.

无论模拟过程是否涉及shell,它的环境都有以下变量集,反映调用用户和命令:SUDO_COMMAND、SUDO_USER、SUDO_UID=、SUDO_GID。

See man sudo and man sudoers for many more subtleties.

看看男人的sudo和人类的sudoers,就会发现更多的微妙之处。

Tip of the hat to @DavidW and @Andrew for inspiration.

向@DavidW和@Andrew致敬。

#2


20  

In BASH, you can find a user's $HOME directory by prefixing the user's login ID with a tilde character. For example:

在BASH中,您可以通过使用一个tilde字符预先设置用户的登录ID来找到用户的$HOME目录。例如:

$ echo ~bob

This will echo out user bob's $HOME directory.

这将响应用户bob的$HOME目录。

However, you say you want to be able to execute a script as a particular user. To do that, you need to setup sudo. This command allows you to execute particular commands as either a particular user. For example, to execute foo as user bob:

但是,您说您希望能够作为特定用户执行脚本。要做到这一点,您需要设置sudo。这个命令允许您作为特定的用户执行特定的命令。例如,要执行foo作为用户bob:

$ sudo -i -ubob -sfoo

This will start up a new shell, and the -i will simulate a login with the user's default environment and shell (which means the foo command will execute from the bob's$HOME` directory.)

这将启动一个新的shell,并且-i将模拟用户的默认环境和shell的登录(这意味着foo命令将从bob的$HOME目录执行)。

Sudo is a bit complex to setup, and you need to be a superuser just to be able to see the shudders file (usually /etc/sudoers). However, this file usually has several examples you can use.

Sudo是一个有点复杂的设置,您需要成为一个超级用户才能够看到shuader文件(通常是/etc/sudoers)。但是,这个文件通常有几个您可以使用的例子。

In this file, you can specify the commands you specify who can run a command, as which user, and whether or not that user has to enter their password before executing that command. This is normally the default (because it proves that this is the user and not someone who came by while the user was getting a Coke.) However, when you run a shell script, you usually want to disable this feature.

在这个文件中,您可以指定您指定谁可以运行一个命令,哪个用户,以及该用户在执行该命令之前是否必须输入密码。这通常是默认的(因为它证明了这是用户,而不是用户得到可乐的时候来的人)。但是,当您运行shell脚本时,通常希望禁用该特性。

#3


12  

For the sake of an alternative answer for those searching for a lightweight way to just find a user's home dir...

为了找到一个替代的答案,寻找一个轻量级的方法来找到一个用户的主目录…

Rather than messing with su hacks, or bothering with the overhead of launching another bash shell just to find the $HOME environment variable...

而不是干扰su的黑客,或者为了找到$HOME环境变量而麻烦启动另一个bash shell的开销……

Lightweight Simple Homedir Query via Bash

There is a command specifically for this: getent

有一个专门针对这个的命令:getent。

getent passwd someuser | cut -f6 -d:

getent passwd someuser | cut -f6 -d:

getent can do a lot more... just see the man page. The passwd nsswitch database will return the user's entry in /etc/passwd format. Just split it on the colon : to parse out the fields.

getent可以做更多的事情…只要看看这个人的页面。passwd nsswitch数据库将返回用户的/etc/passwd格式的条目。将其拆分为冒号:解析字段。

It should be installed on most Linux systems (or any system that uses GNU Lib C (RHEL: glibc-common, Deb: libc-bin)

它应该安装在大多数Linux系统上(或者任何使用GNU Lib C的系统(RHEL: glibc-common, Deb: libc-bin)

#4


3  

You want the -u option for sudo in this case. From the man page:

在这种情况下,你需要sudo的-u选项。从手册页:

The -u (user) option causes sudo to run the specified command as a user other than root.

If you don't need to actually run it as them, you could move to their home directory with ~<user>. As in, to move into my home directory you would use cd ~chooban.

如果您不需要实际运行它,您可以使用~ 来移动到它们的主目录。如进入我的家庭目录,你将使用cd ~chooban。

#5


1  

So you want to:

所以你想:

  1. execute part of a bash script as a different user
  2. 作为不同的用户执行bash脚本的一部分。
  3. change to that user's $HOME directory
  4. 更改为该用户的$HOME目录。

Inspired by this answer, here's the adapted version of your script:

受这个答案的启发,下面是你的剧本的改编版本:

#!/usr/bin/env bash

different_user=deploy

useradd -m -s /bin/bash "$different_user"

echo "Current user: $(whoami)"
echo "Current directory: $(pwd)"
echo

echo "Switching user to $different_user"
sudo -u "$different_user" -i /bin/bash - <<-'EOF'
    echo "Current user: $(id)"
    echo "Current directory: $(pwd)"
EOF
echo

echo "Switched back to $(whoami)"

different_user_home="$(eval echo ~"$different_user")"
echo "$different_user home directory: $different_user_home"

When you run it, you should get the following:

当你运行它时,你应该得到以下信息:

Current user: root
Current directory: /root

Switching user to deploy
Current user: uid=1003(deploy) gid=1003(deploy) groups=1003(deploy)
Current directory: /home/deploy

Switched back to root
deploy home directory: /home/deploy

#6


1  

I was also looking for this, but didn't want to impersonate a user to simply acquire a path!

我也在寻找这个,但是不想模仿用户简单地获取一条路径!

user_path=$(grep $username /etc/passwd|cut -f6 -d":");

user_path=$(grep $username /etc/passwd|cut -f6 -d“:”);

Now in your script, you can refer to $user_path in most cases would be /home/username

现在,在您的脚本中,您可以在大多数情况下引用$user_path作为/home/username。

Assumes: You have previously set $username with the value of the intended users username. Source: http://www.unix.com/shell-programming-and-scripting/171782-cut-fields-etc-passwd-file-into-variables.html

假设:您之前设置了$username,其值为预期用户名。来源:http://www.unix.com/shell-programming-and-scripting/171782-cut-fields-etc-passwd-file-into-variables.html

#7


1  

This works in Linux. Not sure how it behaves in other *nixes.

这是在Linux中。不确定它在其他*nix中的表现。

  getent passwd "${OTHER_USER}"|cut -d\: -f 6

#8


0  

Quick and dirty, and store it in a variable:

又快又脏,把它存储在一个变量中:

USER=somebody
USER_HOME="$(echo -n $(bash -c "cd ~${USER} && pwd"))"

#9


0  

I was struggling with this question because I was looking for a way to do this in a bash script for OS X, hence /etc/passwd was out of the question, and my script was meant to be executed as root, therefore making the solutions invoking eval or bash -c dangerous as they allowed code injection into the variable specifying the username.

我很困扰这个问题,因为我正在寻找一个方法在OS X的bash脚本,因此/ etc / passwd的问题,和我的脚本是作为根用户执行,因此使解决方案调用eval或bash - c危险,因为他们允许代码注入变量指定用户名。

Here is what I found. It's simple and doesn't put a variable inside a subshell. However it does require the script to be ran by root as it sudos into the specified user account.

这是我的发现。它很简单,并没有在子shell中放入一个变量。但是,它确实要求脚本在sudos进入指定用户帐户时由根运行。

Presuming that $SOMEUSER contains a valid username:

假设$SOMEUSER包含一个有效的用户名:

echo "$(sudo -H -u "$SOMEUSER" -s -- "cd ~ && pwd")"

I hope this helps somebody!

我希望这能帮助别人!

#10


0  

If the user doesn't exist, getent will return an error.

如果用户不存在,getent将返回一个错误。

Here's a small shell function that doesn't ignore the exit code of getent:

下面是一个小的shell函数,它不会忽略getent的退出代码:

get_home() {
  local result; result="$(getent passwd "$1")" || return
  echo $result | cut -d : -f 6
}

Here's a usage example:

这里有一个使用的例子:

da_home="$(get_home missing_user)" || {
  echo 'User does NOT exist!'; exit 1
}

# Now do something with $da_home
echo "Home directory is: '$da_home'"