我最初是在不同地询问上问这个问题的,但是管理员说这对于该组来说“太宽泛了”,我应该在这里提出。
我正在尝试创建一个PHP程序,该程序将在localhost上运行,并且需要从连接的USB摄像头设备(我正在开发的摄像头阵列外围设备)拍摄快照。
我正在在 MacBook Pro 上运行的 Mac OS X Mojave 上进行开发。我最终将部署到具有运行Mac OS X的嵌入式Mac Mini或运行Linux的嵌入式Raspberry Pi的信息亭。我正在开发的自定义相机阵列硬件也嵌入在此信息亭中。
我目前在Mac上使用 imagesnap ,并计划在Linux上使用 fswebcam 进行编程拍照。
我已经设置了我作为 localhost 访问的本地Apache Web服务器。我还安装了 PHP 7.1.23 。
我已经编写了一个PHP程序(请参见下文),该程序应列出使用 imagesnap -l </ em>连接到计算机的可用摄像机,然后它应使用 imagesnap对列出的每个摄像机拍摄图像。 -d 。
如果我以自己的用户ID在终端下以CLI模式运行此PHP程序,它将列出相机并拍摄并保存图像。
但是,我打算的部署将在自助服务终端中,该终端具有一个网页界面,该界面在拍摄图像时会调用此PHP程序。
不幸的是,这是一个问题。症状很明显:
当PHP程序以我的用户ID在CLI模式下运行时,它会很好地处理图像并将其写入Web目录的相应子目录中。
% php ../imagesnaptest.php
imagesnap -l RETURNS 'Video Devices:
<AVCaptureDALDevice: 0x7fda89438500 [FaceTime HD Camera][DJH6095K5ZEG1HPBB]>
'
FaceTime HD Camera is a valid camera.
camerasArray =
array(1) {
[0]=>
string(18) "FaceTime HD Camera"
}
imagesnap -d 'FaceTime HD Camera' /Users/myiuserid/Sites/sonascan/scans/img5cd115d73d2b5.jpg RETURNS 'Capturing image from device "<AVCaptureDALDevice: 0x7fb27b32dbb0 [FaceTime HD Camera][DJH6095K5ZEG1HPBB]>"...'
Captured 1 images from cameras.
IMAGING COMPLETE.
但是当通过浏览器的HTTP调用调用该php程序时,它以 _www 身份运行,并且似乎无法访问摄像机,并且没有图像保存到Web目录。但是没有错误消息解释为什么imagesnap失败(甚至承认它已经失败了)。
% imagesnap -l RETURNS ''
camerasArray =
array(0) { }
No valid cameras were found!
我已经开放了我的Web目录的所有人的权限 rwx ,并且这种行为上的差异保持不变。
有人建议我,我的问题是权限配置错误,因为通常 _www 网络服务器用户无法访问连接的USB设备(如相机)。但是,没有人建议我可以改变它。
在探索迄今为止我提出的建议时,我尝试制作了 _www 甚至 root 和< em>甚至在程序上设置了setuid位。这不能解决问题。相反,它引入了一个新错误,该错误生成了错误消息:
*2019-05-06 19:56:44.081 imagesnap[60072:14580598] The application with bundle ID (null) is running setugid(), which is not allowed*
。
评论员 @nohillside 写道:
”这可能是一个简单的访问权限问题,可能是Apache 配置错误,这可能是SIP(系统完整性保护),沙箱或 完整的磁盘访问权限,这可能是其他事情。没有更多 有关设置的详细信息以及您需要进行的一些挖掘(例如,如果您 用仅记录自身的shell脚本替换imagesnap 工作),任何答案都只能是猜测。”
按照 @nohillside 的建议,我将 imagesnap 替换为无法访问相机的程序(“ / usr / local / bin / python3 -h ”,并且在更改程序时没有错误。因此,我认为这与 imagesnap 所需的相机访问有关。
在我看来,这可能与 SIP 或沙箱有关,但我不知道如何更改和测试替代SIP或沙箱配置。如果您了解如何配置这些配置,并有建议供我测试,请更精确地描述如何更改此配置。
我如何才能了解有关如何配置Web服务器以使其以这种方式访问我的相机的更多信息?在哪里可以了解有关SIP和沙箱安全性通常如何工作以及如何运行的更多信息。我应该针对刚刚描述的情况进行调整。
<?php
if (php_sapi_name() == "cli") { $nl= PHP_EOL; } //PHP is running in command line
else { $nl= "<br />"; } // PHP is running in browser }
function getListOfCameras()
{
global $nl;
$imagesnaplist = shell_exec("/usr/local/bin/imagesnap -l");
echo "imagesnap -l RETURNS '" . $imagesnaplist ."' $nl";
$cameraDeviceArray = explode(PHP_EOL,$imagesnaplist );
unset ($cameraDeviceArray[0]); // Throw away "Video Devices:" line in element [0]
$cameraDeviceArray = array_values($cameraDeviceArray); // Reassign elements in array to start at [0] again
$matchedCameras = 0;
$camerasArray =array();
foreach ($cameraDeviceArray as $key => $value)
{
preg_match("/\[(.*?)\]/", $value, $matches);
if ($matches[1] != "")
{
$camerasArray[$matchedCameras] = $matches[1];
echo $camerasArray[$matchedCameras]. " is a valid camera. $nl";
$matchedCameras++;
}
}
return $camerasArray;
}
function takeAPhoto($camera, $filename)
{
global $nl;
$status = shell_exec("/usr/local/bin/imagesnap -d '$camera' $filename ");
echo "imagesnap -d '$camera' $filename RETURNS '" . $status . "'$nl";
return $status;
}
function takeAllPhotos($camerasArray)
{
global $nl;
$numberTaken = 0;
if (count($camerasArray) > 0)
{
foreach ($camerasArray as $camera)
{
$cameraNumber = $numberTaken;
$filename = "/Users/myiuserid/Sites/sonascan/scans/img" . uniqid() . ".jpg";
$status = takeAPhoto($camera, $filename);
$numberTaken++;
}
return $numberTaken;
} else
{
die("No valid cameras were found!$nl");
}
}
$camerasArray = getListOfCameras();
echo "camerasArray = $nl";
var_dump($camerasArray);
echo "$nl";
$numberTaken = takeAllPhotos($camerasArray);
echo "$nl" . "Captured $numberTaken images from $numberOfCameras cameras.$nl";
echo "IMAGING COMPLETE.$nl";
?>