寻找你的手机,Linux之道
这些年来,我弄丢手机的次数多得自己都不好意思承认。每次发生这种情况,我都会感到一阵失落,就像弄丢钥匙,或者开车到家才意识到买的杂货还放在超市的购物车里……在超市。
当我注意到手机不见了时,我不会自动假设它被偷了。相反,我知道我可能只是把它放在了某个地方。如果我认为我可能把它落在家里以外的某个地方,我的首要任务是尽快找到它,以防止它真的被偷。
其他手机平台也有帮助你找到手机的技术,但它们是专有的,最终用户通常无法控制它们的工作方式。还有一种选择是“变砖”你的手机,即你的服务提供商向手机发送信号,擦除并禁用它。我宁愿尽一切努力找到我的手机,然后再考虑使用该选项。
那么,你如何找到你丢失的手机呢?显而易见的事情是尝试拨打它。但是,如果铃声处于静音模式,或者手机超出听力范围怎么办?如果呼叫没有任何结果,并且你正在使用专有的手机平台,你可能需要直接跳到变砖选项,如果该选项对你开放的话。
我目前的手机是诺基亚 N900,最近在Linux 杂志上对其进行了评测(参见 Kyle Rankin 在 2010 年 5 月刊上的评测)。由于 N900 构建在 Linux 之上,并且完全解锁(带有终端应用程序和简单的 root 访问权限),你可以做一些很酷的事情来找到它,而你在其他手机上只能通过使保修失效才能做到(如果你能做到的话)。
首先,这里有一些应该安装的软件包
rootsh 软件包通过以下命令启用对 N900 的 root 访问权限sudo gainroot命令。
OpenSSH 客户端和 OpenSSH 服务器软件包。
这些软件包可从 Maemo Extras 软件包仓库获得。要启用它,请启动应用管理器,单击标题栏以调出菜单,然后选择应用程序目录。选择 maemo.org(在某些手机上可能称为 Maemo Extras),取消选中“禁用”复选框,然后点击“保存”按钮(图 1)。
如果仓库不在那里,你可以通过点击应用程序目录屏幕上的“新建”按钮来添加它。详细信息如下
目录名称:maemo.org。
发行版:fremantle。
组件:free,nonfree。
启用仓库后,点击应用程序管理器主屏幕上的“下载”,并安装这三个软件包。
安装完这些软件包后,我在 N900 上启动了终端应用程序,并将我的公共 SSH 密钥从我的桌面电脑复制过来,就像这样
$ mkdir .ssh $ scp me@desktop:.ssh/id_rsa.pub .ssh/authorized_keys
现在,当我的 N900 连接到我的家庭网络时,我可以ssh从我的桌面电脑登录到它,而无需密码,就像这样
$ ssh user@n900.ip.addr.here
理论上,我也应该能够ssh当手机连接到蜂窝网络时登录到手机;但是,我的蜂窝网络提供商似乎不允许这样做——即使我配置了备用端口,我所有的登录尝试都失败了。
另一个小问题是,SSH 守护进程绑定到它启动时启动的任何网络接口,并且在你切换网络后它不会响应,因为它仍然在监听另一个网络。为了解决这个问题,我创建了一个小的 shell 脚本,并将其放在 /etc/network/if-up.d/01_ssh。为了创建它,我使用了 vi,以 root 权限
$ sudo gainroot $ vi /etc/network/if-up.d/01_ssh
脚本本身只有两行
#!/bin/sh /etc/init.d/ssh restart
创建它之后,我修改了它的权限
$ chmod 755 /etc/network/if-up.d/01_ssh
/etc/network/if-up.d/ 文件夹中的任何脚本都会在接口启动时运行,因此当这种情况发生时,SSH 守护进程将重新启动,并且 SSH 将始终在正确的接口上监听。
现在我已经有了可靠的 SSH 访问(当连接到蜂窝网络以外的网络时),我可以ssh登录到手机,假设我知道 IP 地址。在我的家里,知道 IP 地址很容易,因为我的 DHCP 服务器配置为在 N900 每次连接时始终给它相同的地址。但是当我不家时,我可能不知道,所以我的首要任务是确保 N900 告诉我它的 IP 地址是什么。为此,我只需将以下内容添加到我之前创建的 01_ssh 脚本中
/sbin/ifconfig -a \ | awk '/inet addr/ { print $2 }' \ | awk -F: '{ print $2 }' \ > /tmp/n900.ipaddr
这个单行脚本解析了ifconfig -a的输出,以提取所有 IP 地址,并将其存储在 /tmp/ 文件夹中名为 N900.ipaddr 的文件中。然后,我添加以下行将文件上传到我在我的家庭服务器上创建的一个特殊用户
/usr/bin/scp -i /home/user/.ssh/id_rsa \ /tmp/n900.ipaddr n900user@home.example.net:
在设置此项之前,我需要在 N900 上使用ssh-keygen命令生成一个 SSH 密钥,然后将 .ssh/id_rsa.pub 文件复制到我创建的用于接收文件的非特权用户的 ~/.ssh/authorized_keys 文件中。
现在,每次 N900 上线或连接到新网络时,它都会将 IP 地址上传到我的家庭服务器。无论我在哪里,我只需登录到我的服务器并查看我的 N900 用户的 home 文件夹,我就知道当前的 IP 地址是什么。
如果我可以ssh登录到我的手机,我可以让它做几件事。
首先,我可以使用 MPlayer(可以从应用管理器轻松安装)播放铃声(或任何其他支持的音频文件)
$ mplayer /home/user/MyDocs/.sounds/Ringtones/OuterSpace.aac
即使手机处于静音模式,这也有效。说到静音模式,我可以用以下命令关闭静音模式
$ dbus-send --type=method_call --dest=com.nokia.profiled \ /com/nokia/profiled \ com.nokia.profiled.set_profile \ string:"general"
关闭静音模式后,我可以再次尝试呼叫手机。
可能会出现一个问题,如果我插着耳机。在这种情况下,让我手机震动可能更有意义。要让手机震动,我这样做
$ dbus-send --print-reply --system --dest=com.nokia.mce \ /com/nokia/mce/request \ com.nokia.mce.request.req_vibrator_pattern_activate \ string:PatternIncomingCall
手机会一直震动,直到我用以下命令将其关闭
$ dbus-send --print-reply --system --dest=com.nokia.mce \ /com/nokia/mce/request \ com.nokia.mce.request.req_vibrator_pattern_deactivate \ string:PatternIncomingCall
如果此时我仍然无法找到手机,就该用更高级的方法了。
N900 有一个加速度计和一个前置摄像头。这两者都可以从命令行触发。可以这样告诉摄像头拍照
$ /usr/bin/gst-launch v4l2src \ device=/dev/video1 \ num-buffers=1 ! \ ffmpegcolorspace ! \ jpegenc ! \ filesink location=/tmp/front-camera.jpg
然后可以将生成的 front-camera.jpg 照片上传到我的服务器或其他设备,我可以查看照片,看看是否可以从中判断出手机在哪里。不幸的是,前置摄像头是典型的手机摄像头(不是很好)。如果相机镜头没有被任何东西挡住,并且有极佳的照明,你可能会得到一张不错的照片,但可能不会(图 2)。
加速度计可以告诉我手机是否在移动。我可以用以下命令查看输出
$ watch cat /sys/class/i2c-adapter/i2c-3/3-001d/coord
如果数字每两秒变化很大,则手机正在运动。如果它们变化不大(或根本没有变化),则手机只是放在某个地方。
此时可能有所帮助的一件事是让手机给我打电话,这样我就可以监听手机所在位置发生的事情。要让手机给我打电话,我这样做
$ dbus-send --system --dest=com.nokia.csd.Call \ --type=method_call \ --print-reply /com/nokia/csd/call \ com.nokia.csd.Call.CreateWith \ string:"3215551212" \ uint32:0
这里的3215551212应该替换为要呼叫的电话号码。如果我把手机放在一个有独特声音的地方(如电影院或咖啡馆),我或许能够判断出它放在哪里。
如果我仍然无法弄清楚,就该检查 GPS 了。我把这种方法留到现在,因为它需要一个 Python 库,该库仅在 maemo.org extras-devel 仓库中可用。extras-devel 是一个面向开发人员的仓库,它包含许多尚未完全准备好供普通用户使用的软件包(图 3)。
要启用 extras-devel,请按照 wiki.maemo.org/Extras-devel 上的说明进行操作(参见“如何激活 Extras-devel”部分)。
启用仓库后,我安装了 python-location 软件包,就像这样
$ sudo gainroot $ apt-get install python-location
安装软件包后,我禁用了 extras-devel 仓库,这样我就不会意外地用可能不稳定的版本升级我的任何稳定软件。我通过打开应用管理器应用程序,点击标题栏并选择应用程序目录来做到这一点。然后,我点击我之前创建的 extras-devel 条目,选中“禁用”复选框并点击“保存”。我也可以直接删除它,但我决定保存它以备后用,以防万一。
安装了 python-location 软件包后,我现在可以使用 Python 与 GPS 通信了。但这个计划只有一个问题。我不懂 Python。它已经很久以来一直在我的“要学习的语言”列表中,我保证我总有一天会学会它,但神话般的“总有一天”还没有到来。
值得庆幸的是,一位懂 Python 的 N900 用户编写了一个脚本,它完全满足了我的需求:talk.maemo.org/showpost.php?p=566224&postcount=1。该脚本位于帖子的底部。除了脚本之外,该帖子还包含许多关于恢复 N900 的有用想法(许多与我在此处描述的相似),非常值得一读。像这样运行脚本
$ python gps.py
假设手机在一个可以获得 GPS 定位的地方,它将输出手机的纬度和经度。你可以将这些坐标输入到谷歌地图(或任何其他允许你输入纬度和经度的地图工具)中,你就可以轻松地看到手机在几英尺的范围内。
以上所有技术都存在一个问题。它们都依赖于可以通过 SSH 访问手机。正如我之前所说,我的服务提供商阻止我在手机连接到蜂窝网络时登录。此外,任何时候我的手机连接到 Wi-Fi 网络,它都位于路由器后面,路由器也阻止我使用 SSH 登录。
解决这个问题的方法是让手机在没有我告诉它的情况下尽可能多地执行上述操作。
要解决的第一个问题是如何让手机知道它丢失了。我可以通过在公共 Web 服务器上放置一个特殊命名的文件来做到这一点。一个例子是 http://example.net/~me/my-n900-is-lost.txt。出于安全原因,此文件应具有难以猜测的名称(所以不要使用我的示例)。
如果我让手机尝试wget该文件,并且成功了,手机就会知道它丢失了,并且可以尝试告诉我它在哪里。如果手机尝试wget该文件并失败,它就会知道它没有丢失(至少在我的情况下,目前还没有丢失)。
然后,诀窍是如何让 N900 定期检查以查看它是否丢失。在常规 Linux 机器上,我会使用 cron 来完成此操作,但 N900 没有 cron(原因是电池寿命)。N900 有一个闹钟守护进程,但与它交互需要 Python 知识。一些项目正在努力为 N900 带来类似 cron 的功能,但在(撰写本文时)它们尚未完全准备好供公众使用。
我确实找到了一个软件包,它作为权宜之计足够好,直到其他解决方案成熟。它被称为 dbus-scripts,它是一个 dbus 监控守护进程,允许你在 N900 上发生某些事情时执行脚本。与 python-location 软件包一样,dbus-scripts 在(撰写本文时)仅在 extras-devel 仓库中可用。重新启用仓库后,我安装了该软件包以及 GUI 配置程序,就像这样
$ sudo gainroot $ apt-get install dbus-scripts dbus-scripts-settings
安装软件包后,我再次禁用了 extras-devel。GUI 消除了配置触发器中的一些试错过程,所以我推荐它(图 4)。我将想要执行的命令放入一个名为 lost.sh 的 shell 脚本中,然后在 /etc/dbus-scripts.d/dbus-scripts-settings 文件中设置触发器(列表 1)。
列表 1. lost.sh
#!/bin/sh # A script to help you find your phone. # by Daniel Bartholomew, May 2010 # # This script is licensed under the terms of the # GNU General Public License, version 3 or later. # See <https://gnu.ac.cn/licenses/> for details. # Some variables you need to set: amilost="http://example.net/my-n900-is-lost.txt" # CHANGE THIS! username="username" # the username at your ssh host sshhost="hostname" backupnumber="3215551212" # backup phone that can receive SMS messages # A timestamp variable you can alter if you want to: timestamp=$(/bin/date +%Y-%m-%d-%H.%M.%S-%Z) # With the vars out of the way, we can begin: # The first step is to check for the file on the webserver. # If it exists, we collect data and send it, # if not, we print a message and exit. if wget --output-document=/tmp/${timestamp}.txt \ ${amilost} 2>/dev/null; then # If we're here, the file exists and the phone is lost. # Get the current IP address and send it using the # sendsms.py script: /sbin/ifconfig -a \ | awk '/inet addr/ { print $2 }' \ | awk -F: '{ print $2 }' \ > /tmp/${timestamp}.ip # sendsms.py from: # http://talk.maemo.org/showpost.php?p=558430&postcount=57 /home/user/sendsms.py ${backupnumber} \ "$(/bin/cat /tmp/${timestamp}.ip)" # take a picture with the front-facing camera /usr/bin/gst-launch v4l2src \ device=/dev/video1 \ num-buffers=1 ! \ ffmpegcolorspace ! \ jpegenc ! \ filesink location=/tmp/${timestamp}.jpg # get the location and send it # gps.py from: http://talk.maemo.org/showthread.php?t=47301 /usr/bin/python2.5 /home/user/gps.py 2>&1 > /tmp/${timestamp}.gps /home/user/sendsms.py ${backupnumber} \ "$(/bin/cat /tmp/${timestamp}.gps)" # More things can be done. # See http://wiki.maemo.org/Phone_control for # ideas. Experiment and have fun! # (But don't blame me if you accidentally brick your phone.) # We've gathered the data we want, now copy everything to the sshhost # server # (need to have ssh-keys set up for this to work). /usr/bin/scp -i /home/user/.ssh/id_rsa /tmp/${timestamp}.* \ ${username}@${sshhost}: # What if I want to run more commands than are listed above, # such as making the phone vibrate or having it call me? # The file I downloaded from the server can contain special # commands. If the file is empty, nothing will happen. # This probably is not the most secure thing to do, but if the # phone really has been stolen, this will allow you to pull # data off of it and/or brick the phone on purpose. Be careful! # Only uncomment the following line if you know what you are doing # and are comfortable with the consequences. I am not responsible # if you break your phone. #/bin/sh /tmp/${timestamp}.txt else # if the file on the server doesn't exist the phone is not lost: echo "I am not lost." fi # That's it! We're done. exit 0
我决定监视三种不同的操作最有意义
手机更改网络。
键盘打开或关闭。
低电量。
如果网络发生变化,那可能意味着手机正在移动(可能我把它落在车里了)。如果键盘打开或关闭,则有人正在使用或查看手机。最后,如果手机只是放在那里,最终电池会耗尽(我希望在所有电量耗尽之前找到手机)。
dbus-scripts-settings 中监视这些操作的三行是以下内容
/home/user/lost.sh * * com.nokia.icd * * * CONNECTED /home/user/lost.sh * * org.freedesktop.Hal.Device \ Condition ButtonPressed cover /home/user/lost.sh * * com.nokia.bme.signal battery_low
lost.sh 脚本在每次发生这些事件之一时被调用。dbus-scripts Wiki 页面 (wiki.maemo.org/DbusScripts) 包含有关格式化配置行的更多信息。
有关它做什么的详细信息,请参阅 lost.sh 脚本(列表 1)。我在测试中发现,我在命令行上可以运行的一些命令在被 dbus-scripts 守护进程从脚本中调用时根本不起作用。这些命令包括 mplayer 命令和将手机设置为非静音模式。值得庆幸的是,其他命令在从脚本中调用时可以正常工作。
最后一个难题是让 N900 至少将它收集到的一些数据通过 SMS 发送到另一部手机。我在 talk.maemo.org/showpost.php?p=558430&postcount=57 找到了一个用于发送 SMS 消息的优秀 Python 脚本。
有了 SMS 脚本,并在 lost.sh 脚本中调用它,我所要做的就是在我的 Web 服务器上创建特殊文件,突然我的 N900 开始在我配置的事件之一发生时,向我的指定备用手机(我妻子的手机)发送 SMS 消息。
Daniel Bartholomew 在 Monty Program (montyprogram.com) 担任技术作家和系统管理员。他与妻子和孩子住在北卡罗来纳州,经常可以在 Freenode IRC 上的 #linuxjournal 和 #maria 频道找到他。他还想为他在测试脚本时向妻子发送的所有 SMS 消息道歉。