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. The user running the script and the user writing to the file are different, so I need to sudo to the file owner. Here is the relevant line in the sudoers file :
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:
sudo su - userB -c 'source ./getOpenFiles.sh'
getOpenFiles.sh has this one line:
#!/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:
#!/bin/bash
sudo su - banjobs
lsofResult=$(/usr/sbin/lsof "${sourcePath}")`.
Neither solution is working.
What you actually want is something more like:
Let's go over why the other approaches didn't work one-at-a-time:
Running
source
undersudo su -c
...uses
sudo
to runsu
, which runssh -c 'source ./getOpenFiles.sh'
. This doesn't work for several independent reasons:sh -c 'source ./getOpenFiles.sh'
relies on thesource
keyword being available in/bin/sh
, but this is a bash extension.Even if your
/bin/sh
is provided by bash, this still defeats the purpose of usingsource
: 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 startedsudo su
.Running
sudo su - banjobs
, followed bylsofResult=$(/usr/sbin/lsof "${sourcePath}")
...means that
lsofResult=$(...)
doesn't run until aftersudo su - banjobs
exits. Ifsudo su - banjobs
has exited, then the current user isn'tbanjobs
any more, so thesudo
command has no effect whatsoever on thelsof
.Demonstrating, in detail, how to test this (for folks who don't have a
banoff
oruserB
account on their system):...yields, on my system, output akin to the following:
...showing that the code in question did in fact work as described.