替换用户 mid-Bash-script 并继续 运行 命令 (Mac OSX)

Substitute user mid-Bash-script & continue running commands (Mac OSX)

我正在构建两个脚本,它们结合起来将完全卸载 Mac OS X 上的程序 (Microsoft Lync)。我需要能够从具有 root 访问权限的帐户进行交换(这帐户最初执行第一个脚本)给当前登录的用户。

这是必要的,因为第二个脚本不仅需要由登录用户执行,还需要来自所述用户的 shell。在此示例中,这两个脚本是名称 Uninstall1.shUninstall2.sh

Uninstall1.sh(root用户执行):

#!/bin/bash

#commands ran by root user

function rootCMDs () {

pkill Lync
rm -rf /Applications/Microsoft\ Lync.app
killall cfprefsd

swapUser

}

function swapUser () {

currentUser=$(who | grep console | grep -v _mbsetupuser | grep -v root | awk '{print }' | head -n 1)

cp /<directory>/Uninstall2.sh${currentUser}

su -l ${currentUser} -c "<directory>/{currentUser}/testScript.sh";


<directory> 实际上在脚本中声明了,但为了保护隐私,我将其排除。

在上面的脚本中,我 运行 一些基本命令作为 root 用户将应用程序删除到垃圾箱,并终止 cfprefsd 以防止必须重新启动机器。然后我调用 swapUser 函数,该函数动态识别当前登录的用户帐户并将其分配给变量 currentUser(在我们的环境中的这种情况下,假设只有一个用户登录是安全的一次电脑)。我不确定我是否还需要 cp directory/Uninstall2.sh 部分,但这是为了解决不同的问题。

主要问题是让脚本正确处理 su 命令。我使用 -l 标志来模拟用户登录,这是必要的,因为这不仅替代了登录的用户帐户,而且它作为所述用户启动了一个新的 shell。我需要使用 -l 因为 OS X 不允许从管理员帐户修改另一个用户的钥匙串(有问题的管理员帐户具有 root 访问权限,但不是也不会切换到 root)。 -c意在执行复制的脚本,如下:

Uninstall2.sh(需要本地登录用户执行):

#!/bin/bash


function rmFiles () {
    # rm -rf commands
    # rm -rf commands

certHandler1
}


function certHandler1 () {

myCert=($(security dump-keychain | grep <string> | grep alis | sed -e 's/"alis"<blob>="//' | sed -e 's/"//'))
cLen=${#myCert[@]} # Count the amount of items in the array; there are usually duplicates

for ((i = 0;
      i < ${cLen};
      i++));
      do security delete-certificate -c ${myCert[$i]};
done

certHandler2
}


function certHandler2 () {

# Derive the name of, and delete Keychain items related to Microsoft Lync.

myAccount=$(security dump-keychain | grep KeyContainer | grep acct | sed -e 's/"acct"<blob>="//' | sed -e 's/"//')
   security delete-generic-password -a ${myAccount}

lyncPW=$(security dump-keychain | grep Microsoft\ Lync | sed -e 's/<blob>="//' | awk '{print , }' | sed -e 's/"//')
   security delete-generic-password -l "${lyncPW}"
}


rmFiles


在上面的脚本中,rmFiles 通过从用户的 ~/Library 目录中删除一些文件和目录来启动脚本。这没有问题,假设来自 Uninstall1.shsu 使用本地用户的 shell 正确执行第二个脚本。

然后我使用 security dump-keychain 转储本地用户的 shell,找到一个特定的证书,然后将所有结果分配给 cLen 数组(因为用户的钥匙串中可能有重复项) .然后删除数组中的每个项目,之后动态找到并删除更多钥匙串项目。

我一直在发现的是,第一个脚本将正确地 su 到它找到的登录用户,此时第二个脚本根本不会 运行 。或者,第二个脚本是 运行 作为 root 用户,因此没有正确删除它应该 su 到的已登录用户的钥匙串项目。

抱歉这么长 post,感谢阅读,我期待对这种情况有所了解!

修订
我设法找到一种方法来实现我在单个 bash 脚本中尝试做的所有事情,而不是两个。为此,我让主脚本在 /tmp 中创建另一个 bash 脚本,然后以本地用户身份执行该脚本。我将在下面提供它以帮助可能需要此功能的其他人:

关于如何在 bash 脚本中创建另一个 bash 脚本的代码归功于以下来源:
http://tldp.org/LDP/abs/html/here-docs.html - 示例 19.8

#!/bin/bash

# Declare the desired directory and file name of the script to be created. I chose /tmp because I want this file to be removed upon next start-up.
OUTFILE=/tmp/fileName.sh

(
cat <<'EOF'
#!/bin/bash

# Remove user-local Microsoft Lync files and/or directories
function rmFiles () {

   rm -rf ~/Library/Caches/com.microsoft.Lync
   rm -f ~/Library/Preferences/com.microsoft.Lync.plist
   rm -rf ~/Library/Preferences/ByHost/MicrosoftLync*
   rm -rf ~/Library/Logs/Microsoft-Lync*
   rm -rf ~/Documents/Microsoft\ User\ Data/Microsoft\ Lync\ Data
   rm -rf ~/Documents/Microsoft\ User\ Data/Microsoft\ Lync\ History
   rm -f ~/Library/Keychains/OC_KeyContainer*

certHandler1
}


# Need to build in a loop that determines the count of the output to determine whether or not we need to build an array or use a simple variable.
# Some people have more than one 'PRIVATE_STRING' certificate items in their keychain - this will loop through and delete each one. This may or may not be necessary for other applications of this script.

function certHandler1 () {

# Replace 'PRIVATE_STRING' with whatever you're searching for in Keychain
myCert=($(security dump-keychain | grep PRIVATE_STRING | grep alis | sed -e 's/"alis"<blob>="//' | sed -e 's/"//'))
cLen=${#myCert[@]} # Count the amount of items in the array

   for ((i = 0;
        i < ${cLen};
        i++));
      do security delete-certificate -c ${myCert[$i]};
   done

certHandler2
}

function certHandler2 () {

# Derive the name of, then delete Keychain items related to Microsoft Lync.
myAccount=$(security dump-keychain | grep KeyContainer | grep acct | sed -e 's/"acct"<blob>="//' | sed -e 's/"//')
   security delete-generic-password -a ${myAccount}

lyncPW=$(security dump-keychain | grep Microsoft\ Lync | sed -e 's/<blob>="//' | awk '{print , }' | sed -e 's/"//')
   security delete-generic-password -l "${lyncPW}"

}

rmFiles


exit 0

EOF
) > $OUTFILE

# -----------------------------------------------------------

# Commands to be ran as root
function rootCMDs () {
 pkill Lync
 rm -rf /Applications/Microsoft\ Lync.app
 killall cfprefsd # killing cfprefsd mitigates the necessity to reboot the machine to clear cache.

 chainScript

}

function chainScript () {

if [ -f "$OUTFILE" ]
then
  # Make the file in /tmp executable. This is necessary for /tmp as a non-root user cannot access files in this directory.
  chmod 755 $OUTFILE
  # Dynamically identify the user currently logged in. This may need some tweaking if multiple User Accounts are logged into the same computer at once.
  currentUser=$(who | grep console | grep -v _mbsetupuser | grep -v root | awk '{print }' | head -n 1);
  su -l ${currentUser} -c "bash /tmp/UninstallLync2.sh"

else
  echo "Problem in creating file: \"$OUTFILE\""
fi

}


#  This method also works for generating
#+ C programs, Perl programs, Python programs, Makefiles,
#+ and the like.

# Commence the domino effect.
rootCMDs

exit 0

# -----------------------------------------------------------


干杯!