【问题标题】:How to scan in PHP如何在 PHP 中扫描
【发布时间】:2014-12-11 23:35:50
【问题描述】:

我想从我的 PHP 脚本中进行扫描。我正在使用 Ubuntu 14.04 LTS、Brother MFC-7840W 扫描仪(位于工作场所)和 Brother MFC-9840CDW(位于家中)。当任一扫描仪作为网络扫描仪连接到计算机时,我可以从终端和 PHP 进行扫描。但是,当任一扫描仪作为 USB 扫描仪连接到计算机时,我无法从 PHP 扫描(我仍然可以从终端扫描)。

为什么我的 PHP 脚本无法访问 USB 扫描仪,但 $USER 可以?

我在工作中提出了这个问题,但现在我在家,所以我将展示我从我的 PHP 脚本访问 Brother MFC-9840CDW USB 扫描仪的尝试。

这是我用来扫描的 PHP 代码的 sn-p:

if($_POST['ScanDevice'] == "brother3:net1;dev0") // if MFC-7840W network scanner
{$scanner = escapeshellarg($_POST['ScanDevice']);} 
elseif($_POST['ScanDevice'] == "brother3:bus3;dev1") // if MFC-7840W USB scanner
{$scanner = escapeshellarg($_POST['ScanDevice']);}
elseif($_POST['ScanDevice'] == "brother3:net1;dev1") // if MFC-9840CDW network scanner
{$scanner = escapeshellarg($_POST['ScanDevice']);}
elseif($_POST['ScanDevice'] == "brother3:bus6;dev1") // if MFC-9840CDW USB scanner
{$scanner = escapeshellarg($_POST['ScanDevice']);}

$command = "scanimage -d {$scanner} --resolution {$_POST[ScanResolution]} --mode {$_POST[ScanColor]}  > {$filename}";

echo exec($command,$op,$result);
if($result > 0)
{die("ERROR");}

PHP 脚本适用于网络扫描仪,但不适用于 USB 扫描仪。
如果我选择任一 USB 扫描仪(当前为 MFC-9840CDW)并运行脚本,则文件 /var/log/apache2/error.log 显示:

scanimage: open of device brother3:bus6;dev1 failed: Invalid argument  

问题来了:设备brother3:bus6;dev1 存在吗?

这是scanimage --list-devices在家中终端输入时显示的内容(MFC-9840CDW所在的位置):

[pixma] udp_command: No data received (select): timed out
[pixma] udp_command: No data received (select): timed out
[pixma] udp_command: No data received (select): timed out
[pixma] Cannot read scanner make & model: �+�&
device `brother3:net1;dev1' is a Brother MFC-7840W SCANNER
device `brother3:net1;dev0' is a Brother MFC-9840CDW Scanner-MFC-9840CDW
device `brother3:bus6;dev1' is a Brother MFC-9840CDW USB scanner

为了证明 USB 扫描仪适用于 $USER,我在终端中输入以下命令:

scanimage --test -d 'brother3:bus6;dev1'  

其中显示:

scanimage: rounded value of br-x from 215.9 to 215.88
scanimage: rounded value of br-y from 355.6 to 355.567
scanimage: scanning image of size 1664x2776 pixels at 24 bits/pixel
scanimage: acquiring RGB frame, 8 bits/sample
scanimage: reading one scanline, 4992 bytes...  PASS
scanimage: reading one byte...      PASS
scanimage: stepped read, 2 bytes...     PASS
scanimage: stepped read, 4 bytes...     PASS  

为了证明用户 www-data 无法访问 USB 扫描仪,我在终端中输入以下命令:

sudo -u www-data scanimage --test -d 'brother3:bus6;dev1'  

其中显示:

scanimage: open of device brother3:bus6;dev1 failed: Invalid argument

【问题讨论】:

  • Apache可能没有权限使用你的硬件,导致打开失败。您可以使用 su/sudo 在以 apache 用户身份运行的 shell 中尝试该命令。无论如何,您必须授予您的用户一些权限才能被允许扫描,对 apache 的用户执行相同操作,或者为 scanimage 为 apache 创建一个 sudo 条目。
  • @Carpetsmoker 我说过要尝试冒充apache用户来尝试并修复权限。否则,授予 sudo 但 only 用于 scanimage 命令,这没什么大不了的。这是最著名的 sudo 用例之一(授予命令子集)。
  • 请不要在代码块中使用<br> 和反引号。使用 Markdown 代码格式 - 选择块并单击“代码”按钮(或每行缩进四个空格)。
  • 也许www-data 用户(或您系统上的任何东西)的有限权限没有设置HOME 或其他所需的环境变量?我发现有一些系统命令。
  • 你应该在你所有的shell参数上使用escapeshellarg,否则你可以注入任意shell命令。

标签: php linux scanning


【解决方案1】:

PHP 无法访问 USB 扫描仪,因为 www-data(运行 PHP 脚本的用户)不是 USB 扫描仪所属组的成员。将用户 www-data 添加到 USB 扫描仪所属的组。

要查找 USB 扫描仪所属的组,必须知道 USB 扫描仪的名称。要查找 USB 扫描仪的名称,请输入命令:

lsusb -v  

其中显示(在其他行中):

Bus 002 Device 007: ID 04f9:01cc Brother Industries, Ltd  

然后,通过输入命令找到USB扫描仪所属的组:

ls -al /dev/bus/usb/002/007  

其中显示:

crw-rw-r--+ 1 root lp 189, 134 Dec 12 22:30 /dev/bus/usb/002/007  

USB 扫描仪所属的组是lp。 $USER 能够访问 USB 扫描仪的原因是因为 $USER 是 lp 组的成员,而 www-data 不是。这通过输入命令来演示:

grep ^lp /etc/group  

其中显示:

lp:x:7:root,arya  

通过输入以下命令将用户 www-data 添加到组 lp

sudo usermod -a -G lp www-data  

然后,再次测试结果,输入grep ^lp /etc/group,现在显示:

lp:x:7:root,arya,www-data  

然后,重新启动 apache 以确保上述操作已注册:

sudo apache2ctl -k restart  

然后,测试www-data是否可以从终端访问USB扫描仪:

sudo -u www-data scanimage --test -d 'brother3:bus6;dev1'  

其中显示:

scanimage: rounded value of br-x from 215.9 to 215.88  
scanimage: rounded value of br-y from 355.6 to 355.567  
scanimage: scanning image of size 1664x2776 pixels at 24 bits/pixel  
scanimage: acquiring RGB frame, 8 bits/sample  
scanimage: reading one scanline, 4992 bytes...  PASS  
scanimage: reading one byte...      PASS  
scanimage: stepped read, 2 bytes...     PASS  
scanimage: stepped read, 4 bytes...     PASS  

然后,再次运行原始 PHP 脚本,看看它是否可以访问 USB 扫描仪并扫描文档...

成功了!

【讨论】:

    猜你喜欢
    • 2021-05-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-16
    • 1970-01-01
    • 1970-01-01
    • 2016-08-15
    相关资源
    最近更新 更多