我有一个bash脚本,它将登录到远程设备并复制文件。如果以用户(支持)身份登录或运行\
,它可以从命令行完美运行sudo -u support -i '/opt/IIS/getScreenShot' <parameter>
支持用户在每台设备上都设置了密钥,因此不会在getScreenShot
bash脚本的scp命令中询问密码。
我现在需要这个脚本能够被Apache调用/运行。我有一个执行以下操作的PHP脚本:
$output = shell_exec("sudo -u support -i '$command' $serial");
其中$command
为/opt/IIS/getScreenShot
。
该命令将开始运行(输出回浏览器)。如果通过Apache服务器调用bash脚本中的[ ! -d /tmp/$1 ];
或mkdir -p /tmp/$1
等命令似乎没有执行,我不确定原因。
我原本以为sudo命令会像支持用户一样运行它,就像从命令行那样,但它不是。最终我需要/opt/IIS/getScreenShot
能够从命令行和Apache调用运行。有什么建议吗?
编辑:
sudoers entry:
apache ALL=(ALL) NOPASSWD: ALL
/ opt / IIS / getScreenShot将在浏览器中显示echo语句时运行。只是脚本中的某些命令不会。 getScreenShot是:
set -e
#set -x
#Check runnable
if [ $# -lt 1 ] ; then #Check there is enough command line parameters.
echo "Usage: $0 [<Serial#> | <Socket#>] "
echo " Example: $0 GESC637005W1 "
exit 1
fi
_socket=$(/opt/Allure/socketdata "$1" |awk -F '[(/: ]'+ '{print $10}')
#echo "socket $_socket"
if [ $_socket = "400" ];
then
echo "400 Serial number not found"
exit 400
fi
echo "Checking for dir /tmp/$1"
if [ ! -d /tmp/$1 ]; then
echo "mkdir -p /tmp/$1"
mkdir -p /tmp/$1;
fi
echo "test"
echo "scp -P$_socket support@localhost:/srv/samba/share/clarity-client/client-apps/digital-poster/screens/screenshot.png /tmp/$1/screenshot.png"
scp -P$_socket support@localhost:/srv/samba/share/clarity-client/client-apps/digital-poster/screens/screenshot.png /tmp/$1/screenshot.png
return=$?
if [ $return -ne 0 ];
then
echo "401 scp1 failed $return"
exit 401
fi
echo "test2"
scp /tmp/$1/screenshot.png support@172.24.16.37:/opt/digital_media/dm_content/screenshots/$1.png
return=$?
if [ $return -ne 0 ];
then
echo "402 scp2 failed $return"
fi
快速更新以澄清我的实际问题。该脚本将实际运行,并且参数将正确传递给它。问题是某些命令&#39;在脚本中将无法正常运行,它似乎主要与测试/创建目录有关。如果目录不存在,则测试&#39;因为它不起作用。另外,如果我删除测试但是直接发出mkdir命令(在确定目录不存在之后 - 或者删除它是否存在),mkdir会显示错误:mkdir:无法创建目录&#39; / tmp / GESC637005UH&# 39;:文件存在。我直接检查了目录,但它不在那里。我已经在系统上运行了locate命令而无法找到它,所以我不确定为什么mkdir命令认为它在那里 - 并且也可能解释为什么测试&#39;似乎“失败”#39; (即它认为它存在)。
答案 0 :(得分:0)
这是尝试重构您的脚本。我已经在线添加了一些评论,但这里的主要内容是使用mktemp
使用保证唯一的文件,并在完成trap
后清理它。其他一些小的评论:
if
和shell的其他流控制语句的目的是正好来运行命令并检查其结果代码。您应该很少需要在条件中明确检查$?
(例如,将其包含在诊断消息中,当然显然是有用的)。我删除了您的评论并添加了一些我自己的评论,这些评论可能无法保留在生产脚本中。
#!/bin/sh
set -e
if [ $# -lt 1 ] ; then
# >&2 sends diagnostics to standard error
echo "Usage: $0 [<Serial#> | <Socket#>] " >&2
echo " Example: $0 GESC637005W1 " >&2
exit 1
fi
# Encapsulate error exit in a convenient function
die () {
rc=$1
shift
# include $0 in all diagnostic messages
echo "$0: $@" >&2
exit "$rc"
}
_socket="$(/opt/Allure/socketdata "$1" |awk -F '[(/: ]'+ '{print $10}')"
[ $_socket = "400" ] || die 200 "Serial number $1 not found (socket $_socket)"
# Create a temporary file for this script
t=$(mktemp -t screenshot.XXXXXXXXXX) || exit
# Remove the temporary file on regular or error exit or signal
trap 'rm -f $t' EXIT ERROR HUP INT TERM
scp -P$_socket support@localhost:/srv/samba/share/clarity-client/client-apps/digital-poster/screens/screenshot.png "$t" ||
die 201 "401 scp1 failed $?"
scp "$t" support@172.24.16.37:/opt/digital_media/dm_content/screenshots/"$1".png ||
die 202 "402 scp2 failed $?"
在separate Stack Overflow question
中更详细地解释了die
功能
foo || bar
只是
if foo; then
: nothing here
else
bar
fi
您可以几乎等同地说if ! foo; then bar; fi
但如果foo
未成功运行,则会丢失失败退出代码。 (同样,foo && bar
相当于if foo; then bar; fi
)