我正在构建两个脚本,它们将完全卸载Mac OS X上的程序(Microsoft Lync)。我需要能够从具有root访问权限的帐户(此帐户最初执行第一个脚本)进行交换当前登录的用户。
这是必要的,因为第二个脚本不仅需要由登录用户执行,还需要由所述用户的shell执行。在此示例中,这两个脚本的名称为Uninstall1.sh
和Uninstall2.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 $1}' | 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不允许从管理员帐户修改其他用户的钥匙串(相关管理员帐户具有超级用户权限,但不是也不会切换根)。 -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 $2, $3}' | sed -e 's/"//')
security delete-generic-password -l "${lyncPW}"
}
rmFiles
在上面的脚本中,rmFiles
通过从用户的~/Library
目录中删除一些文件和目录来关闭脚本。假设来自su
的{{1}}使用本地用户的shell正确执行第二个脚本,这没有问题。
然后我使用Uninstall1.sh
转储本地用户的shell,找到一个特定的证书,然后将所有结果分配给security dump-keychain
数组(因为用户可能会重复此项目&#39} ; s钥匙串)。然后删除数组中的每个项目,之后动态查找和删除更多的钥匙串项目。
我发现的第一个脚本将正确cLen
到它找到的登录用户,此时第二个脚本根本不运行。或者,第二个脚本以root用户身份运行,因此无法从登录用户{@ 1}}中正确删除钥匙串项。
对不起,很长的帖子,感谢阅读,我期待着对这种情况有所了解!
答案 0 :(得分:0)
<强>修订强>
我设法找到一种方法来实现我在单个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 $2, $3}' | 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 $1}' | 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
# -----------------------------------------------------------
干杯!