简体   繁体   English

将源与包含sudo命令的脚本一起使用

[英]Use source with script that contains sudo command

I have a script that copies files between servers. 我有一个脚本可以在服务器之间复制文件。 I am using the lsof command to make sure that the file is not being written to before being moved. 我正在使用lsof命令来确保在移动文件之前未将其写入。 The user running the script and the user writing to the file are different, so I need to sudo to the file owner. 运行脚本的用户和写入文件的用户不同,因此我需要对文件所有者进行sudo操作。 Here is the relevant line in the sudoers file : 这是sudoers文件中的相关行:

userA ALL=(userB:userB) NOPASSWD: ALL

In the main script (ran as userA), I have tried calling sudo then the subscript containing the lsof command: 在主脚本(以userA身份运行)中,我尝试调用sudo,然后调用包含lsof命令的下标:

sudo su - userB -c 'source ./getOpenFiles.sh'

getOpenFiles.sh has this one line: getOpenFiles.sh具有这一行:

#!/bin/bash 
lsofResult=$(/usr/sbin/lsof "${sourcePath}")

I have also tried calling the subscript: 我也尝试调用下标:

source ./getOpenFiles.sh

Then have the first line of the subscript be the sudo: 然后使下标的第一行为sudo:

#!/bin/bash
sudo su - banjobs
lsofResult=$(/usr/sbin/lsof "${sourcePath}")`.

Neither solution is working. 两种解决方案均无效。

What you actually want is something more like: 您实际上想要的更像是:

lsofResult=$(sudo -u banjobs lsof "${sourcePath}")

Let's go over why the other approaches didn't work one-at-a-time: 让我们讨论一下为什么其他方法不能一次起作用:

  • Running source under sudo su -c sudo su -c下运行source

     sudo su - userB -c 'source ./getOpenFiles.sh' 

    ...uses sudo to run su , which runs sh -c 'source ./getOpenFiles.sh' . ...使用sudo运行su ,而su运行sh -c 'source ./getOpenFiles.sh' This doesn't work for several independent reasons: 由于几个独立的原因,这不起作用:

    1. sh -c 'source ./getOpenFiles.sh' relies on the source keyword being available in /bin/sh , but this is a bash extension. sh -c 'source ./getOpenFiles.sh'依赖于/bin/sh可用的source关键字,但这是bash扩展。

    2. Even if your /bin/sh is provided by bash, this still defeats the purpose of using source : By starting a new copy of /bin/sh and sourcing your script into that, you're defining the variable in the new shell , not in the original shell that started sudo su . 即使您的/bin/sh由bash提供,这仍然无法实现使用source的目的:通过启动/bin/sh的新副本并将脚本源代码化,您可以在新的shell中定义变量,而不是在启动sudo su的原始shell中

  • Running sudo su - banjobs , followed by lsofResult=$(/usr/sbin/lsof "${sourcePath}") 运行sudo su - banjobs ,然后运行lsofResult=$(/usr/sbin/lsof "${sourcePath}")

    ...means that lsofResult=$(...) doesn't run until after sudo su - banjobs exits. ...意味着lsofResult=$(...)直到sudo su - banjobs退出后才运行。 If sudo su - banjobs has exited, then the current user isn't banjobs any more, so the sudo command has no effect whatsoever on the lsof . 如果sudo su - banjobs已经退出,则当前用户不再是banjobs ,因此sudo命令对lsof无效。


Demonstrating, in detail, how to test this (for folks who don't have a banoff or userB account on their system): 详细说明如何测试(针对在系统上没有banoffbanoff帐户的userB ):

# place relevant contents in sourceme.bash
# switching from lsof to fuser for this test since OS X lsof does not accept a directory
# as an argument.
cat >sourceme.bash <<'EOF'
lsofResult=$(sudo -u root fuser "${sourcePath}" 2>&1)
EOF

# set sourcePath in the outer shell
sourcePath=$PWD
source sourceme.bash
declare -p lsofResult

...yields, on my system, output akin to the following: ...在我的系统上,产量类似于以下内容:

declare -- lsofResult="/Users/chaduffy/tmp: 17165c 17686c 17687c 17688c 17689c 17690c"

...showing that the code in question did in fact work as described. ...表明所讨论的代码实际上按所述方式工作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM