为 Kodi 自制遥控器

通过运行在 Android 手机上的自制遥控器来控制你的家庭媒体播放器。

Kodi 是一款很优秀的软件,能够将几乎所有电脑变身成媒体中心。它可以播放音乐和视频,显示图片,甚至还能显示天气预报。为了在配置成家庭影院后方便使用,你可以通过手机 app 访问运行在连接到 Wi-Fi 的 XBMC 机器上的服务来控制它。可以找到很多这种工具,几乎覆盖所有智能手机系统。

为 Kodi 自制遥控器
为 Kodi 自制遥控器

XBMC

Kodi 原名叫做 XBMC,在你阅读这篇文章的时候,XBMC 已经成为历史。因为法律原因(因为名字 XBMC 或 X-Box Media Center 里引用了不再支持的过时硬件)项目组决定使用新的名字 Kodi。不过,除了名字,其他的都会保持原样。或者说除开通常新版本中所期待的大量新改进。这一般不会影响到遥控软件,它应该能在已有的 XBMC 系统和新的 Kodi 系统上都能工作。

我们目前已经配置好了一个用于播放音乐的 Kodi 系统,不过我们找到的所有 Kodi 遥控没一个好用的,特别是和媒体中心连接的电视没打开的时候。它们都有点太复杂了,集成了太多功能在手机的小屏幕上。我们希望能有这样的系统,从最开始就是设计成只用于访问音乐库和电台插件,所以我们决定自己实现一个。它不需要用到 Kodi 的所有功能,因为除了音乐以外的任务,我们可以简单地切换使用通用的 Kodi 遥控。我们的测试系统是一个刷了 RaspBMC 发行版的树莓派,但是我们要做的工具并不受限于树莓派或Kodi那个发行版,它应该可以匹配任何安装了相关插件的基于 Linux 的 Kodi 系统。

首先,遥控程序需要一个用户界面。大多数 Kodi 遥控程序都是独立的 app。不过对于我们要做的这个音乐控制程序,我们希望用户可以不用安装任何东西就可以使用。显然我们需要使用网页界面。Kodi 本身自带网页服务器,但是为了获得更多权限,我们还是使用了独立的网页框架。在同一台电脑上跑两个以上网页服务器没有问题,只不过它们不能使用相同的端口。

有几个网页框架可以使用。而我们选用 Bottle 是因为它是一个简单高效的框架,而且我们也确实用不到任何高级功能。Bottle 是一个 Python 模块,所以这也将是我们编写服务器模块的语言。

你应该能在软件包管理器里找到 Bottle。在基于 Debian 的系统(包括 RaspBMC)里,你可以通过下面的命令安装:

sudo apt-get install python-bottle

遥控程序实际上只是连接用户和系统的中间层。Bottle 提供了和用户交互的方式,而我们将通过 JSON API 来和 Kodi 交互。这样可以让我们通过发送 JSON 格式消息的方式去控制媒体播放器。

我们将用到一个叫做 xbmcjson 的简单 XBMC JASON API 封装。足够用来发送控制请求,而不需要关心实际的 JSON 格式以及和服务器通讯的无聊事。它没有包含在 PIP 包管理中,所以你得直接从 GitHub 安装:

git clone https://github.com/jcsaaddupuy/python-xbmc.git
cd python-xbmc
sudo python setup.py install

万事俱备,只欠代码。

先从 Bottle 开始

我们程序的基本结构:

from xbmcjson import XBMC
from bottle import route, run, template, redirect, static_file, request
import os
xbmc = XBMC("http://192.168.0.5/jsonrpc", "xbmc", "xbmc")
@route('/hello/')
def index(name):
return template('

Hello {{name}}!

', name=name) run(host="0.0.0.0", port=8000)

这样程序将连接到 Kodi(不过实际上用不到);然后 Bottle 会开始提供网站服务。在我们的代码里,它将监听主机 0.0.0.0(意味着允许所有主机连接)的端口 8000。它只设定了一个站点,就是 /hello/XXXX,这里的 XXXX 可以是任何内容。不管 XXXX 是什么都将作为参数名传递给 index()。然后再替换进去 HTML 网页模版。

你可以先试着把上面内容写到一个文件(我们取的名字是 remote.py),然后用下面的命令启动:

python remote.py

然后你可以在浏览器里访问 localhost:8000/hello/world 看看模版生效的效果。

@route() 用来设定网页服务器的路径,而函数 index() 会返回该路径的数据。通常是返回由模版生成的 HTML 页面,但是并不是说只能这样(后面会看到)。

随后,我们将给应用添加更多页面入口,让它变成一个全功能的 Kodi 遥控,但仍将采用相同代码结构。

XBMC JSON API 接口可以从和 Kodi 机器同网段的任意电脑上访问。也就是说你可以在自己的笔记本上开发,然后再布置到媒体中心上,而不需要浪费时间上传每次改动。

模版 – 比如前面例子里的那个简单模版 – 是一种结合 Python 和 HTML 来控制输出的方式。理论上,这俩能做很多很多事,但是会非常混乱。我们将只是用它们来生成正确格式的数据。不过,在开始动手之前,我们先得准备点数据。

Paste

Bottle 自带网页服务器,我们用它来测试遥控程序。不过,我们发现它性能有时不够好。当我们的遥控程序正式上线时,我们希望页面能更快一点显示出来。Bottle 可以和很多不同的网页服务器配合工作,而我们发现 Paste 用起来非常不错。而要使用的话,只要简单地安装(Debian 系统里的 python-paste 包),然后修改一下代码里的 run 调用:

run(host=hostname, port=hostport, server="paste")

你可以在 http://bottlepy.org/docs/dev/deployment.html 找到如何使用其他服务器的相关细节。

从 Kodi 获取数据

XBMC JSON API 分成 14 个命名空间:JSONRPC, Player, Playlist, Files, AudioLibrary, VideoLibrary, Input, Application, System, Favourites, Profiles, Settings, Textures 和 XBMC。每个都可以通过 Python 的 XBMC 对象访问(Favourites 除外,明显是个疏忽)。每个命名空间都包含许多方法用于对程序的控制。例如,Playlist.GetItems() 可以用来获取某个特定播放列表的内容。服务器会返回给我们 JSON 格式的数据,但 xbmcjson 模块会为我们转化成 Python 词典。

我们需要用到 Kodi 里的两个组件来控制播放:播放器和播放列表。播放器处理播放列表并在每首歌结束时从列表里取下一首。为了查看当前正在播放的内容,我们需要获取正在工作的播放器的 ID,然后根据它找到当前播放列表的 ID。这个可以通过下面的代码来实现:

def get_playlistid():
player = xbmc.Player.GetActivePlayers()
if len(player['result']) > 0:
playlist_data = xbmc.Player.GetProperties({"playerid":0, "properties":["playlistid"]})
if len(playlist_data['result']) > 0 and "playlistid" in playlist_data['result'].keys():
return playlist_data['result']['playlistid']
return -1

如果当前没有播放器在工作(就是说,返回数据的结果部分的长度是 0),或者当前播放器没有处理播放列表,这样的话函数会返回 -1。其他时候,它会返回当前播放列表的数字 ID。

当我们拿到当前播放列表的 ID 后,就可以获取该列表的细节内容。按照我们的需求,有两个重要的地方:播放列表里包含的项,以及当前播放所处的位置(已经播放过的项并不会从播放列表移除,只是移动当前播放位置)。

def get_playlist():
playlistid = get_playlistid()
if playlistid >= 0:
data = xbmc.Playlist.GetItems({"playlistid":playlistid, "properties": ["title", "album", "artist", "file"]})
position_data = xbmc.Player.GetProperties({"playerid":0, 'properties':["position"]})
position = int(position_data['result']['position'])
return data['result']['items'][position:], position
return [], -1

这样可以返回正在播放的项开始的列表(因为我们并不关心已经播放过的内容),而且也包含了用来从列表里移除项的位置信息。

为 Kodi 自制遥控器
为 Kodi 自制遥控器

API 文档在这里:http://wiki.xbmc.org/?title=JSON-RPC_API/v6。它列出了所有支持的函数,但是关于具体如何使用的描述有点太简单了。

JSON

JSON 是 JavaScript Object Notation 的缩写,最初设计用于 JavaScript 对象的序列化。目前仍然起到这个作用,但是它也是用来编码任意数据的一种很好用的方式。

JSON 对象都是这样的格式:

{property1:value1, property2:value2, property3:value3}

支持任意数目的属性/值配对。对 Python 程序员来说,看上去和字典数据结构很相似,不过这两个确实很像。

在字典数据结构里,值本身可以是另一个 JSON 对象,或者一个列表,所以下面的格式也是正确的:

{"name":"Ben", "jobs":["cook", "bottle-washer"], "appearance": {"height":195, "skin":"fair"}}

JSON 通常在网络服务中用来发送和接收数据,并且大多数编程语言都能很好地支持,所以如果你熟悉 Python 的话,你应该可以使用你熟悉的编程语言调用相同的接口来轻松地控制 Kodi。

整合到一起

把之前的功能连接到 HTML 页面很简单:

@route('/juke')
def index():
current_playlist, position = get_playlist()
return template('list', playlist=current_playlist, offset = position)

只需要抓取播放列表(调用我们之前定义的函数),然后将结果传递给负责显示的模版。

负责显示列表数据的模版的主要部分是:

Currently Playing:

% if playlist is not None: % position = offset % for song in playlist: {{song['title']}} % if song['type'] == 'unknown': Radio % else: {{song['artist'][0]}} % end % if position != offset: remove % else: skip % end
% position += 1 % end

可以看到,模版大部分是用 HTML 写的,只有一小部分用来控制输出的其他代码。用两个大括号括起来的变量是输出位置(像我们在第一个 ‘hello world’ 例子里看到的)。你也可以嵌入以百分号开头的 Python 代码。因为没有缩进,你需要用一个 % end 来结束当前的代码块(就像循环或 if 语句)。

这个模版首先检查列表是否为空,然后遍历里面的每一项。每一项会用粗体显示歌曲名字,然后是艺术家名字,然后是一个是否跳过(如果是当前正在播的歌曲)或从列表移除的链接。所有歌曲的类型都是 ‘song’,如果类型是 ‘unknown’,那就不是歌曲而是网络电台。

/remove/ 和 /skip/ 路径只是简单地封装了 XBMC 控制功能,在改动生效后重新加载 /juke:

@route('/skip/')
def index(position):
print xbmc.Player.GoTo({'playerid':0, 'to':'next'})
redirect("/juke")
@route('/remove/')
def index(position):
playlistid = get_playlistid()
if playlistid >= 0:
xbmc.Playlist.Remove({'playlistid':int(playlistid), 'position':int(position)})
redirect("/juke")

当然,如果不能往列表里添加歌曲的话那这个列表管理功能也不行。

因为一旦播放列表结束,它就消失了,所以你需要重新创建一个,这会让事情复杂一些。而且有点让人迷惑的是,播放列表是通过调用 Playlist.Clear() 方法来创建的。这个方法也还用来删除包含网络电台(类型是 unknown)的播放列表。另一个麻烦的地方是列表里的网络电台开始播放后就不会停,所以如果当前在播网络电台,也会需要清除播放列表。

这些页面包含了指向 /play/ 的链接来播放歌曲。通过下面的代码处理:

@route('/play/')
def index(id):
playlistid = get_playlistid()
playlist, not_needed= get_playlist()
if playlistid < 0 or playlist[0]['type'] == 'unknown':
xbmc.Playlist.Clear({"playlistid":0})
xbmc.Playlist.Add({"playlistid":0, "item":{"songid":int(id)}})
xbmc.Player.open({"item":{"playlistid":0}})
playlistid = 0
else:
xbmc.Playlist.Add({"playlistid":playlistid, "item":{"songid":int(id)}})
remove_duplicates(playlistid)
redirect("/juke")

最后一件事情是实现 remove_duplicates 调用。这并不是必须的 - 而且还有人并不喜欢这个 - 不过可以保证同一首歌不会多次出现在播放列表里。

我们也实现了一些页面用来列出收藏歌曲里所有艺术家,以及列出指定艺术家的歌曲和专辑。这些都非常简单,和 /juke 页面基本类似。

为 Kodi 自制遥控器
为 Kodi 自制遥控器

还需要处理一下 UI,不过功能已经有了。

日志

通常拿到 XBMC JSON API 并不清楚能用来做什么,而且它的文档也有点模糊。找出如何使用的一种方式是看别的遥控程序是怎么做的。如果打开日志功能,就可以在使用其他遥控程序的时候看到哪个 API 被调用了,然后就可以应用到在自己的代码里。

要打开日志功能,把 Kodi 媒体中心 接到显示器上,再依次进入设置 > 系统 > 调试,打开允许调试日志。在打开日志功能后,还需要登录到 Kodi 机器上(比如通过 SSH),然后就可以查看日志了。日志文件的位置应该显示在 Kodi 界面左上角。在 RaspBMC 系统里,文件位置是 /home/pi/.xbmc/temp/xbmc.log。你可以通过下面的命令实时监视哪个 API 接口被调用了:

cd /home/pi/.xbmc/temp
tail -f xbmc.log | grep "JSON"

增加功能

上面的代码都是用来播放 Kodi 媒体库里的歌曲的,但我们还希望能播放网络电台。每个插件都有自己的独立 URL 可以通过普通的 XBMC JSON 命令来获取信息。举个例子,要从电台插件里获取选中的电台,可以使用;

@route('/radio/')
def index():
my_stations = xbmc.Files.GetDirectory({"directory":"plugin://plugin.audio.radio_de/stations/my/", "properties":
["title","thumbnail","playcount","artist","album","episode","season","showtitle"]})
if 'result' in my_stations.keys():
return template('radio', stations=my_stations['result']['files'])
else:
return template('error', error='radio')

这样可以返回一个可以和歌曲一样能添加到播放列表的文件。不过,这些文件能一直播下去,所以(之前说过)在添加其他歌曲的时候需要重新创建列表。

共享歌曲

除了伺服页面模版,Bottle 还支持静态文件,方便用于那些不会因为用户输入而改变的内容。可以是 CSS 文件,一张图片或是一首 MP3 歌曲。在我们的简单遥控程序里(目前)还没有任何用来美化的 CSS 或图片,不过我们增加了一个下载歌曲的途径。这个可以让媒体中心变成一个存放歌曲的 NAS 盒子。在需要传输大量数据的时候,最好还是用类似 Samba 的功能,但只是下几首歌到手机上的话使用静态文件也是很好的方式。

通过歌曲 ID 来下载的 Bottle 代码:

@route('/download/')
def index(id):
data = xbmc.AudioLibrary.GetSongDetails({"songid":int(id), "properties":["file"]})
full_filename = data['result']['songdetails']['file']
path, filename = os.path.split(full_filename)
return static_file(filename, root=path, download=True)

应用的时候,只需要为 /songsby/ 页面里的相应 ID 加个链接。

我们已经把所有的代码过了一遍,不过还需要一点工作来把它们集合到一起。可以自己去 GitHub 页面 https://github.com/ben-ev/xbmc-remote 看下。

设置

我们的遥控程序已经开发完成,还需要保证让它在媒体中心每次开机的时候都能启动。有几种方式,最简单的是在 /etc/rc.local 里增加一行命令来启动。我们的文件位置在 /opt/xbmc-remote/remote.py,其他文件也和它一起。然后在 /etc/rc.local 最后的 exit 0 之前增加了下面一行。

cd /opt/xbmc-remote && python remote.py &

GitHub

这个项目目前还只是个架子,但是 - 我们运营杂志就意味着没有太多自由时间来编程。不过,我们启动了一个 GitHub 项目,希望能持续完善, 而如果你觉得这个项目有用的话,欢迎做出贡献。

要查看最新的进展,请访问 https://github.com/ben-ev/xbmc-remote 看看所处的状态。你可以从页面里获取最新的代码,或者通过命令行复制。

如果你希望改善它,可以复制项目到你自己的分支开发,然后在功能完成后发起合并请求。关于如何使用 GitHub 的更多信息,请访问 https://github.com/features


via: http://www.linuxvoice.com/xbmc-build-a-remote-control/

作者:Ben Everard 译者:zpl1025 校对:wxy

本文由 LCTT 原创翻译,Linux中国 荣誉推出

来源:https://linux.cn/article-5877-1.html

Linux:升级到 CentOS 5.6 的注意事项

  CentOS 5.6 是 CentOS 5 发行系列的第六次更新。它包含了很多错误修正、升级和新功能。在往下读之前我们推荐您先阅读 UOP 的发行注记(或单页发行注记)及技术性注记(或单页技术性注记)。本文档的额外部分只作为一个附录并主要涉及关于 CentOS 的问题。   如果你之前已经安装了CentOS 5.5,打算在近期升级到 CentOS 5.6,那么以下内容是你需要关注的:   首先,做好备份(你应该知道应该备份什么),这个不用多说。   然后,执行以下命令:

  1. yum clean all
  2. yum update glibc\*
  3. yum update yum\* rpm\* python\*
  4. yum clean all
  5. yum update

复制代码

  reboot这样就升级完了,可以检查一下系统目前的版本:

  1. lsb_release  -a

复制代码

  注意:如果你的 CentOS 上安装了 ISPConfig,那么有可能会启动了 CentOS Testing 软件源:-kbs-CentOS-Testing,这可能会造成依赖性问题。   用以下命令升级可以禁止 kbs-CentOS-Testing:

  1. yum update –exclude=“postfix” –disablerepo=kbs-CentOS-Testing

复制代码

该贴已经同步到 DeadFire的微博

 

本文内容由 DeadFire 提供

 

 已同步至 wxy的微博

Linux:Linux 下的 QQ 使用方案

QQ在中国的重要性不用多说了,再次前我整理过两份【Ubuntu下的QQ总集】,但是随着时间的推移,有的应用已经无法使用或者无法很好的使用了,所以在这里重新整理一下,删除掉一些QQ方案。

此次整理,只有在Ubuntu 11.10实验通过才发上来,对于部分无法兼容新版本Ubuntu的QQ方案,不予采纳,但是会在文章末尾提一下,有兴趣可以去试。

一、Q+  Web

Q+  Web可以说是第四代Web QQ,是前Web QQ融合Q+开放平台的一个Web OS,除了基础的QQ聊天外,可以使用应用市场中收录的总多优秀的网页应用

目前Q+ Web已经相当成熟,QQ相关的服务如好友管理、群管理、屏蔽功能、修改备注、文件传送、视频会话、抖动窗口、修改个人信息以及导出信息(以网页的形式打包、提供下载)等QQ聊天服务都完善了。

Q+  Web是目前Linux下最优秀的QQ使用方案,而且腾讯那边也完全可以以此来推脱QQ4Linux的发布。

使用方法:

直接访问http://web.qq.com/

二、 Q+ Web桌面化:pyWebQQ

pyWebQQ是 基于python、python-webkit包装的webqq桌面版,相比直接网页版的Q+ Web:

  • 系统托盘
  • 桌面信息提醒
  • 独立使用webkit内核,长期在线不会影响到你浏览器的效率

劣势就是需要安装

安装方式:

sudo apt-add-repository ppa:linux-deepin-team/linux-deepin
sudo apt-get update
sudo apt-get install pywebqq

或者到Ubuntu中文论坛下载:http://forum.ubuntu.org.cn/viewtopic.php?f=73&t=342725

Deb包:https://launchpad.net/~linux-deepin-team/+archive/linux-deepin/+files/pywebqq_0%2Br12-2_all.deb

三、LibQQ

LibQQ是国内一些能人发起的一个QQ项目,该项目是更新Pidgin中的QQ协议。 使用起来感觉很好,但是还是有些BUG,根据使用者的说法,该QQ得到了比较广泛的赞扬。

这个项目在今年上半年更新活跃,但是五月份以后就停止更新了。

目前能在Pidgin使用(Empathy中无法使用),但是根据网页在我的微博 @灵亦rEd 中的反馈来看,这个项目现在使用起来没有那么流畅了,没两天就会被要求到QQ安全中心去激活一次(非所有用户都是这样,仅由部分用户会这样)。

但是不管怎么说,LibQQ这个项目给那些喜欢简洁的人留下了深刻的印象。

安装方式:

sudo add-apt-repository ppa:lainme/libqq
sudo apt-get update
sudo apt-get install libqq-pidgin

注意,这个是Pidgin的一个插件,所以要先安装Pidgin

项目主页:http://code.google.com/p/libqq-pidgin

四、CreQQ

CreQQ是由sneezry达人写的一个Chrome 插件,基本完成了QQ的聊天功能,但是由于完善版本还在开发中,所以大家可以到作者的博客去关注Creqq的动态:http://sneezry.com/

在这里也意思意思放个图片吧:

上面的QQ方案就是我推荐大家使用的,其余下面简单提一下:

1.WQQ ,是对webqq两个版本所做的一个桌面应用,也就是说是不在通常浏览器里的而在小窗口里的webqq。对于已收未读消息、非聊天窗口下的消息会通过弹出 ubuntu的notify进行提醒,其中的亮点是提醒用的图片是用户/群所设定的头像。不支持Ubuntu 11.10 下载地址:http://code.google.com/p/zhscript/downloads/list

2.gtk-qq ,是一款基于 webqq 协议,使用 gtk+ 开发的 linuxqq 客户端 ,目前还没完善,项目主页:https://github.com/kernelhcy/gtkqq

3.miniqq,是官方的迷你webQQ,但是经常掉线,所以不推荐(如果解决了掉线的问题,那倒是不错的选择),使用地址:http://w.qq.com/

4.WineQQ, 通过Wine来安装Win下的QQ,最出名的是深度论坛的达人开发的deewine项目,不过不支持Ubuntu 11.10。在现在Q+ Web那么强大的情况下,实在不推荐大家使用Wine来模拟蛋疼的QQ,无法享受完美的QQ体验之余,还要承受大量的资源消耗。

5.QQ4Linux官方版,一个烂尾货,闲得蛋疼就去试试吧。

来自:http://www.ubuntusoft.com/discussion/26/linux下的qq使用方案/

Linux:MangoDB?!不是MongoDb!

MangoDB 宣称自己是比 MongoDB 更可靠更快速的版本,而且只有 30 行代码。

下面是来自 MangoDB 首页上的介绍:

MangoDB 是最快的数据库之一,它允许你存放任意类型的数据,没有任何 IO 瓶颈。如果你熟悉 MongoDB,那么你使用 MangoDB 会很顺手,你无需任何操作就可立即映射已有的数据到一个全新的自动 SHARTING 算法。

关键是该软件只有 30 行代码:

from gevent.server import StreamServer
import os


def mangodb(socket, address):
    socket.sendall('HELLO\r\n')
    client = socket.makefile()
    output = open('/dev/null', 'w')
    while 1:
        line = client.readline()
        if not line:
            break
        cmd_bits = line.split(' ', 1)
        cmd = cmd_bits[0]
        if cmd == 'BYE':
            break
        if len(cmd_bits) > 1:
            output.write(cmd_bits[1])
            if os.environ.get('MANGODB_DURABLE', False):
                output.flush()
                os.fsync(output.fileno())
            client.write('OK' + os.urandom(1024).encode('string-escape') + '\r\n')
        client.flush()


if __name__ == '__main__':
    server = StreamServer(('0.0.0.0', 27017), mangodb)
    print ('Starting MangoDB on port 27017')
    server.serve_forever() 

Getting Started

先安装 gevent:

easy_install -U gevent

然后运行服务器:

python server.py

用你的MongoDB客户端连接到本机的27017端口看看?

你可以得到和MongoDB一样的功能,但是它更快!

 

VIA http://houwenhui.gotoip2.com/archives/1373

Linux:Linux 中引号的那些事

引号

 

我们将把编写脚本的事情暂时搁在一边,然后来讨论一些,我们一直在用的,但是没有解释的东西。引号在这一节里面,我们会讲述引号。引号有两个作用:

  1. 控制字符替换 和
  2. 执行将单词包含在一起的功能

我们已经使用过引号。在我们的脚本里面,将文本信息赋值给常量的赋值操作就使用了引号:

在上面这个例子中,文本信息是被双引号包括住的。我们使用双引号的原因是—我们要把所有单词包括住,当作一个整体来对待。如果我们没有使用引号,那么bash解释器,就会将所有位于第一个单词后面的单词,解释为其他的命令(第一个单词被解释为命令)。

尝试一下运行下面的命令,看看有什么效果出来:

 

单引号和双引号 

shell解释器可以识别双引号和单引号。 下面的复制表达式效果是等价的:

然而,在双引号和单引号之间存在一个重要的差别。 单引号,在字符替换方面有限制。 正如我们在上一节所看到的内容一样,你可以将一个变量放在双引号里面,而shell解释器依然会对变量执行字符替换的操作。 

我们可以通过使用echo命令来查看这种效果: 

如果我们将上述的双引号改为单引号,那么,行为将会改变:

双引号并没有限制—以”$”开头的变量的字符替换,不过,它的确对通配符的扩展效果进行了限制。比如,下面这个例子:

引用单个字符 

还有另外一种引用字符你会碰到的。 它就是反斜杠。The backslash tells 反斜杠告诉shell解释器忽略反斜杠符后面的第一个字符。比如:

通过使用反斜杠符,shell解释器忽略了对”$”符号进行解释。既然shell已经忽略了”$”,那么,shell解释器也就不会对$HOSTNAME执行字符替换了。 下面,给出一个更有用例子:

 

正如你所看到的,通过使用反斜杠符号,我们可以将双引号包含在文本里面。

反斜杠的其他使用技巧

如果,你阅读过任何软件的使用手册,并且这手册是由GNU项目完成的,那么,你会发现,在软件的命令选项中,除了以一个下划线_加一个字母的形式出现之外,还有,以两个下划线加一个完整的单词的形式出现。例如,下面两个语句是等价的:

 

为什么在软件中,这两种形式都是支持的呢?短的那种形式,是专门为那些懒的输入员而设定的,而长的那种形式,是专门为写脚本而存在的。我有时候,是混合着使用上面的两种形式,然后,我发现采用长的命令选项有用,如果,我写了一个脚本,并且,我将在几个月后去阅读它。看到长的命令选项,有助于我理解这个命令选项是什么意思,从而省却我去查man手册的功夫。现在多敲几下键盘,会以后节省很多功夫。 这样,懒惰的原则就保持住了。

你有可能会疑虑,使用长的命令形式,会导致一个单独的命令变得很长。 为了与这个问题斗争,你可以使用反斜杠来让shell解释器忽略换行符号,正如下面的操作:

这样使用反斜杠,可以让我们将每行的内容包含在一个单独的命令中。让这个技巧可以应用,要注意的地方:换行,必须在反斜杠后面马上出现(也就是,在输入了反斜杠之后,就必须换行了)。 如果,你将一个空格符放置在反斜杠后面,那么,空格符号会被忽略,而不是换行符被忽略。反斜杠符,也可以被用于,将特殊的符号插入到文本。special characters into our text. 这些符号,被叫做—转移字符,下面就有一些转移字符:

转义字符 …………………..

名字

可能的用途

n

换行符

添加空白行在文本中

t

制表符

将水平制表符添加到文本中

a

提醒

让你的终端发出嘟嘟声。

\

反斜杠

插入一个反斜杠符

f

formfeed

Sending this to your printer ejects thepage

转移字符的应用很常见。非常常见转移字符,这个想法,首先出现在C语言里面。编程语言今天,shell解释程序,C++,perl,python,awk,tcl和其他程序语言都使用了转移字符这个概念。通过使用echo命令的-e选项,我们将展示上述转移字符的应用:

 

来自:http://article.yeeyan.org/view/90556/299613

Linux:linux下部署goagent

下载以下两个软件

1.Google App Engine SDK for Python

https://developers.google.com/appengine/downloads?hl=zh-CN#Google_App_Engine_SDK_for_Python

2.goagent

https://code.google.com/p/goagent/

在此提供已经包含goagent的google appengine压缩包 http://pan.baidu.com/share/link?shareid=472887&uk=1493434283  (goagent 3.0.1)

下载后解压,将解压后的goagent文件夹放到google_appengine目录下,我的目录结构如下:~/google_appengine/goagent-goagent-d488f2

准备好申请的Google application_ID与两步验证密码,如何申请请问google

下来是配置goagent

编辑~/google_appengine/goagent-goagent-d488f2/local/proxy.ini

填写正确的appid,在此建议将profile由默认的google_cn改为google_hk,编辑完成后保存退出

运行以下命令更新app

aquan@edge ~/google_appengine $ python appcfg.py update goagent-goagent-d4488f2/server/python/
07:03 PM Host: appengine.google.com
07:03 PM Application: wrchiublog; version: 1
07:03 PM
Starting update of app: wrchiublog, version: 1
07:03 PM Getting current resource limits.
Email: wrchiu@126.com  //在此填写googleid
Password for wrchiu@126.com:    //此处填写两步验证密码,而不是帐号密码
07:04 PM Scanning files on local disk.
07:04 PM Cloning 1 static file.
07:04 PM Cloning 6 application files.
07:04 PM Uploading 1 files and blobs.
07:04 PM Uploaded 1 files and blobs
07:04 PM Compilation starting.
07:04 PM Compilation completed.
07:04 PM Starting deployment.
07:04 PM Checking if deployment succeeded.
07:04 PM Deployment successful.
07:04 PM Checking if updated app version is serving.
07:04 PM Completed update of app: wrchiublog, version: 1

更新完成后便可以使用以下命令开是appengine/goagent-goagent-d4488f2/local $ python proxy.py

注意:有时在更新app时会出现如下错误

aquan@edge ~/google_appengine $ python appcfg.py update goagent-goagent-d4488f2/server/python/
07:00 PM Host: appengine.google.com
Error parsing yaml file:
Unable to assign value 'your_appid' to attribute 'application':
Value 'your_appid' for application does not match expression
  '^(?:(?:[a-z\d\-]{1,100}\~)?(?:(?!\-)[a-z\d\-\.]{1,100}:)?(?!-)[a-z\d\-]{0,99}[a-z\d])$'
  in "goagent-goagent-d4488f2/server/python/app.yaml", line 1, column 14

可按照提示修改goagent-goagent-d4488f2/server/python/app.yaml中的application为正确的appid

至此linux下goagent部署完成,推荐使用chromium浏览器配合Proxy SwitchySharp插件,使用方法可以参考这里

以上操作在linuxmint 15下实现

via http://aotee.com/linux-and-goagent

Linux:RHEL/CentOS系统的社区维护资源整合

Linux各个发行版的技术上虽然有差别,但一般不至于有很大鸿沟,实际上更复杂的其实是各个发行版的维护社区的工作方式和交流文化的差别,如果不了解去利用相应的社区资源,就会觉得维护这个发行版异常吃力,从而产生“XXX发行版不好用”的错觉。

因为工作原因最近我接触维护的系统多为CentOS,之前对CentOS的印象都是“又古老又难维护”,不过几个月的积累下来,发现RH系的社区资源并不比Debian/Ubuntu的少,只不过是国内的维护文化和他们的相去甚远,几乎无法兼容,以致很多人都缺乏了解,所以觉得需要撰文列举下这些资源。

以下很多第三方仓库都在Centos Wiki有介绍

仓库列表

维护仓库的通常是一群维护者,有个论坛、邮件列表等,有什么需求,或者有什么BUG,可以直接去和维护者沟通。下面都是列出了主页的一些仓库,留意主页的链接可以找到交流方法了。

官方仓库

默认安装的CentOS的yum,/etc/yum.repos.d/CentOS-Base.repo是基本的源仓库;里面各个仓库名下mirrorlist是官方列表,yum的fastestmirror插件会从其中选择一个来更新;而如果注释了mirrorlist写baseurl,就只从这一个仓库更新了。可以参考163源的CentOS5-Base-163.repo

这些是CentOS/RedHat官方维护的,就是那些“老旧过时”而且“几乎什么都没”,只要不是出现严重漏洞都不会更新那些。

FedoraProject for EPEL

Fedora和Redhat的关系就不详述了,就是FedoraProject里有个“EPEL Special Interest Group”,为EPEL系维护的一个社区仓库,基本上加上这个仓库后就能丰富了整个EPEL生态了,在Debian系里面“理所当然源里就有”的那些软件就会有了,比如openvpn,htop,ipcalc,git … 虽然版本不会很新,但起码能用了。

用法:安装这些链接页面里面的.rpm。

RPM Fusion

这个仓库说提供的是FedoraProject跟RedHat都不想提供的程序,提供的分类就知道怎么回事了,基本都是Sound and Video,Games and Entertainment,Hardware Support等等。首先是Linux平台下多媒体支持方面的版权问题非常复杂,ffmpeg/x264等通常都有一些争议行的授权,当然也有nvidia/ati等硬件的闭源驱动、Oracle的闭源版Virtualbox等,把他们独立出来避免争端。

另外这个仓库基本提供的更新都是for Fedora,EPEL5/6的几乎没更新。可以说RPMFusion是个“桌面仓库”,而且国内163源提供了RPMFusion的镜像

用法: 见Configuration

RepoForge

原叫RPMForge,和CentOS社区较紧密,提供的包也比较海量的,很难评价分什么方向,CentOS Wiki专门有页面提供安装指导,因为包的数量太海量了很难和“FedoraProject for EPEL”做比较。

用法: 见Usage

Remi

这个仓库依赖EPEL。

提供了php54 / mysql55 / firefox 等等的更新,选的软件比较符合Web开发者工作的需要,当然服务器最好也是维护相同版本。这个仓库使用了github来管理软件包的spec,可以直接看他提供了什么包。更新非常紧贴各个软件的官方发布。

用法: 安装主页相应的remi-release-XX.rpm

KBS-Extras

CentOS本来的维护团队,有趣的一点是这仓库基本全在-testing里面提供软件包。

FedoraHosted – SoftwareCollections

这是重点推荐的。这不是一个仓库,是很多个。里面的软件包和上述那些仓库不大一样,都是在/opt下建立一套专用的目录,避免在/usr里面打架的软件包;这里提供了php/python/ruby/perl/mysql/postgre/apache等常用“服务器生态”。

用法:各个Collection的repo链接。

FedoraHosted

上述的只是FedoraHosted内一个子仓库,FedoraHosted是类似Ubuntu的PPA社区的环境,维护者可以通过建立自己的帐号然后建立一些自选软件的仓库。里面应该还有很多有用的东西待发掘。

Fedora People Repositories

一样是类似Ubuntu的PPA,不过这里就多数偏向Fedora的更新,也有些有EPEL6。

Pramberger, pp

这个仓库主要提供EPEL 3/4/5等旧版本的一些包的更新,有php,python的第三方模块、qt、squid等的更新,大概还是偏向更新服务器环境的吧。

用法:保存http://devel.pramberger.at/getrepo?release=到/etc/yum.repos.d,注意替换release参数(3|4|5)。

ELRepo

偏内核的新硬件支持模块。

IUS Community Repo

提供PHP, Python, MySQL更新,不过感觉更新不够Remi紧密。

PS.维护技巧

yum的仓库选择

/etc/yum.repos.d/下的文件记录着各个仓库的信息,上述很多仓库在安装之后会在这里生成一个.repo,但里面的仓库不一定被启用了,里面可能写了enabled=0。

一般来说,为了避免系统升级时候和第三方的包出现冲突,第三方的仓库都应该enabled=0,在需要使用、查找其中软件时候,使用yum的参数:

yum –enablerepo=remi install firefox-langpack-fr

下载SRPM

一定需要定制编译特定软件时候,这些仓库都提供SRPM仓库的,但是默认可能没开启。(yumdownloader需要安装yum-utils)

yumdownloader –enablerepo=epel-source –source php

Yum/Rpm常用命令

Rpm/dpkg、yum/apt-get对照

http://www.pixelbeat.org/docs/packaging.html 

via http://os.51cto.com/art/201306/400424.htm 

Linux:用Python来SSH连接到你的机器

是时间写点python代码了。我爱自动化的东西,今天我将告诉大家怎么使用python通过ssh连接你的机器,并在上面运行命令。这并不难,但是用python来做也不是很简单,因为要用很多模块和库来完成这个任务。 你是不是很好奇本教程将会使用什么模块呢?

我们将使用Python中 pexpect 模块的 pxssh 类,它用于处理一些自动化的需求,比如ssh和ftp。想使你的系统管理生活尽可能的简单吗?那么,请关注本教程并且尝试尽可能多的学习吧。OK,OK,看我这里,下面我将给出关于pxssh的一些简单的描述。你也可以在python的交互shell导入pxssh 后,键入help(pxssh)以得到更多关于pxssh的信息。

pxssh介绍

pxssh 基于pexpect。它是pexpect.spawn的扩展类,专门用来建立SSH连接。我经常使用python的pxssh进行ssh连接。 pxssh 使用shell提示符从远程主机来同步输出。为了使这更牛x,它把shell提示符设置的比$或#还独特。这应该可以在大多数Borne/bash或csh shell上工作。

你可以在这里看到更多关于pxssh。

现在开始吧。

第一步,我们导入所有需要的东西,并且给机器详情分配变量,就像图解1.

 

Linux:用Python来SSH连接到你的机器
Linux:用Python来SSH连接到你的机器

图解 1

之后我们创建一个函数,使用pxssh创建并开始一个到ssh服务器的连接。

 

Linux:用Python来SSH连接到你的机器
Linux:用Python来SSH连接到你的机器

图解 2

请仔细学习我们是是怎么用try和except来处理错误的.在这里可以阅读更多关于python的错误处理.

下一步是什么?

下一步是在两个机器间的ssh连接建立之后,创建一个函数来给机器发送命令.

 

图解 3

 

Linux:用Python来SSH连接到你的机器
Linux:用Python来SSH连接到你的机器

图解 4

关闭文件并保存它. 现在它已经准备好可以运行了.

 

via: http://www.unixmen.com/use-python-ssh-machine/

本文由 LCTT 原创翻译,Linux中国 荣誉推出

译者:flsf 校对:jasminepeng

来源:https://linux.cn/article-2090-1.html

Linux:ps命令的10个例子

Linux ps 命令

linux的ps命令是一个查看系统运行的进程的一个最基础的工具。它提供了一个当前进程的快照,还带有一些具体的信息,比如用户id,cpu使用率,内存使用,命令名等,它不会像top或者htop一样实时显示数据。虽然它在功能和输出上更加简单,但它仍然是每个linux新手需要了解和学好的必要进程管理/检测工具。

Linux:ps命令的10个例子
Linux:ps命令的10个例子

在本篇中,我们会学习ps命令基本的用法:查找、过滤,以不同的方式排序。

语法说明

ps命令有两种不同风格的语法规则:BSD风格和UNIX风格。Linux新手经常感到困惑并会误解这两种风格,所以在继续下一步之前,我们来弄清楚一些基本的信息。

注意: “ps aux”不等同于”ps -aux”。比如”-u”用于显示用户的进程,但是”u”意味着显示具体信息。

BSD 形式 – BSD形式的语法的选项前没有破折号,如:

ps aux

UNIX/LINUX 形式 – linux形式的语法的选项前有破折号,如:

ps -ef

在linux系统上混合这两种语法是可以的。比如 “ps ax -f”。但是本章中我们主要讨论UNIX形式语法。

如何使用ps命令

1. 显示所有进程

下面的命令可以显示所有进程的列表。

$ ps ax
$ ps -ef

通过管道输出到”less”可以分页。

使用”u”或者”-f”选项可以显示进程的具体信息。

$ ps aux
$ ps -ef -f

为什么USER列显示的不是我的用户名,但是其他的像root,www-data等却显示? 对于所有的用户(包括你们的),如果长度大于8个字符,那么ps只会显示你的UID而不是用户名。

2. 显示用户进程

使用”-u”选项后跟用户名来过滤所属用户的进程。多个用户名可以用逗号分隔。

$ ps -f -u www-data
UID        PID  PPID  C STIME TTY          TIME CMD
www-data  1329  1328  0 09:32 ?        00:00:00 nginx: worker process
www-data  1330  1328  0 09:32 ?        00:00:00 nginx: worker process
www-data  1332  1328  0 09:32 ?        00:00:00 nginx: worker process
www-data  1377  1372  0 09:32 ?        00:00:00 php-fpm: pool a.localhost
www-data  1378  1372  0 09:32 ?        00:00:00 php-fpm: pool a.localhost
www-data  4524  2359  0 10:03 ?        00:00:00 /usr/sbin/apache2 -k start
www-data  4527  2359  0 10:03 ?        00:00:00 /usr/sbin/apache2 -k start
www-data  4528  2359  0 10:03 ?        00:00:00 /usr/sbin/apache2 -k start

3. 通过名字或者进程id显示进程

通过”-C”选项后面加上名字或者命令来搜索进程。

$ ps -C apache2
  PID TTY          TIME CMD
 2359 ?        00:00:00 apache2
 4524 ?        00:00:00 apache2
 4525 ?        00:00:00 apache2
...

要通过进程id显示进程,就使用”-p”选项,并且还可以通过逗号分隔来指定多个进程id。

$ ps -f -p 3150,7298,6544

“-C”必须提供精确的进程名,并且它并不能通过部分名字或者通配符查找。为了更灵活地搜索进程列表,通常使用grep命令。

$ ps -ef | grep apache

4. 通过cpu或者内存使用排序进程

系统管理员通常想要找出那些消耗最多内存或者CPU的进程。排序选项会基于特定的字段或者参数来排序进程列表。

可以用’–sort’指定多个字段,并用逗号分割。除此之外,字段前面还可以跟上’-‘或者’+’的前缀来相应地表示递减和递增排序。这里有很多的用于排序的选项,通过man页来获取完整的列表。

$ ps aux --sort=-pcpu,+pmem

显示前5名最耗cpu的进程。

$ ps aux --sort=-pcpu | head -5
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root         1  2.6  0.7  51396  7644 ?        Ss   02:02   0:03 /usr/lib/systemd/systemd --switched-root --system --deserialize 23
root      1249  2.6  3.0 355800 30896 tty1     Rsl+ 02:02   0:02 /usr/bin/X -background none :0 vt01 -nolisten tcp
root       508  2.4  1.6 248488 16776 ?        Ss   02:02   0:03 /usr/bin/python /usr/sbin/firewalld --nofork
silver    1525  2.1  2.3 448568 24392 ?        S    02:03   0:01 /usr/bin/python /usr/share/system-config-printer/applet.py

5. 以树的形式显示进程层级

许多进程实际上是从同一个父进程fork出来的,了解父子关系通常是很有用的。”–forest” 选项会构造一个ascii艺术形式的进程层级视图。

下面的命令会用apache2的进程名来搜索并构造一个树来显示具体信息。

$ ps -f --forest -C apache2
UID        PID  PPID  C STIME TTY          TIME CMD
root      2359     1  0 09:32 ?        00:00:00 /usr/sbin/apache2 -k start
www-data  4524  2359  0 10:03 ?        00:00:00  _ /usr/sbin/apache2 -k start
www-data  4525  2359  0 10:03 ?        00:00:00  _ /usr/sbin/apache2 -k start
www-data  4526  2359  0 10:03 ?        00:00:00  _ /usr/sbin/apache2 -k start
www-data  4527  2359  0 10:03 ?        00:00:00  _ /usr/sbin/apache2 -k start
www-data  4528  2359  0 10:03 ?        00:00:00  _ /usr/sbin/apache2 -k start

不要在排序中使用树状显示,因为两者都会以不同方式影响显示的顺序。

6. 显示父进程的子进程

下面一个是找出所有从apache进程fork出来的进程的例子。

$ ps -o pid,uname,comm -C apache2
  PID USER     COMMAND
 2359 root     apache2
 4524 www-data apache2
 4525 www-data apache2
 4526 www-data apache2
 4527 www-data apache2
 4528 www-data apache2

第一个属于root的进程是apache2的主进程,其他的apache进程都是从主进程fork出来的。下面的命令使用apache2主进程的pid列出了所有的apache2的子进程。

$ ps --ppid 2359
  PID TTY          TIME CMD
 4524 ?        00:00:00 apache2
 4525 ?        00:00:00 apache2
 4526 ?        00:00:00 apache2
 4527 ?        00:00:00 apache2
 4528 ?        00:00:00 apache2

7. 显示进程的线程

“-L”选项会随着进程一起显示线程。它可用于显示所有指定进程或者所有进程的线程。

下面的命令会显示进程id为3150的进程的所有线程。

$ ps -p 3150 -L

8. 改变显示的列

ps命令可以被配置用来只显示被选中的列。很多列可以被用来显示,完整的列表可以查看man页。

下面的命令会只显示pid、用户名、cpu、内存、命令列。

$ ps -e -o pid,uname,pcpu,pmem,comm

同样可以重命名列的名字。

$ ps -e -o pid,uname=USERNAME,pcpu=CPU_USAGE,pmem,comm
  PID USERNAME CPU_USAGE %MEM COMMAND
    1 root           0.0  0.0 init
    2 root           0.0  0.0 kthreadd
    3 root           0.0  0.0 ksoftirqd/0
    4 root           0.0  0.0 kworker/0:0
    5 root           0.0  0.0 kworker/0:0H
    7 root           0.0  0.0 migration/0
    8 root           0.0  0.0 rcu_bh
    9 root           0.0  0.0 rcuob/0
   10 root           0.0  0.0 rcuob/1

非常灵活。

9. 显示进程运行的时间

运行的时间指的是,进程已经运行的时间。运行时间的列并没有默认显示,需要使用-o选项带入。

$ ps -e -o pid,comm,etime

10. 将ps转换为实时进程查看器

通常上,watch命令可将ps命令变成实时进程查看器。像这个简单的命令

$ watch -n 1 'ps -e -o pid,uname,cmd,pmem,pcpu --sort=-pmem,-pcpu | head -15'

我桌面上的输出如下。

Every 1.0s: ps -e -o pid,uname,cmd,pmem,pcpu --...  Sun Dec  1 18:16:08 2013

  PID USER     CMD                         %MEM %CPU
 3800 1000     /opt/google/chrome/chrome -  4.6  1.4
 7492 1000     /opt/google/chrome/chrome -  2.7  1.4
 3150 1000     /opt/google/chrome/chrome    2.7  2.5
 3824 1000     /opt/google/chrome/chrome -  2.6  0.6
 3936 1000     /opt/google/chrome/chrome -  2.4  1.6
 2936 1000     /usr/bin/plasma-desktop      2.3  0.2
 9666 1000     /opt/google/chrome/chrome -  2.1  0.8
 3842 1000     /opt/google/chrome/chrome -  2.1  0.8
 4739 1000     /opt/google/chrome/chrome -  1.8  1.0
 3930 1000     /opt/google/chrome/chrome -  1.7  1.0
 3911 1000     /opt/google/chrome/chrome -  1.6  0.6
 3645 1000     /opt/google/chrome/chrome -  1.5  0.4
 3677 1000     /opt/google/chrome/chrome -  1.5  0.4
 3639 1000     /opt/google/chrome/chrome -  1.4  0.4

输出会每秒刷新状态,但是这其实很top不同。你会发现top/htop命令的输出相比上面的ps命令刷新得更频繁。

这是因为top输出是结合了cup使用值和内存使用值后的排序值。但是上面的ps命令是一个更简单的行为的排序,每次获取一列(像学校的数学),因此它不会像top那样快速更新。


via: http://www.binarytides.com/linux-ps-command/

译者:geekpi 校对:Caroline

本文由 LCTT 原创翻译,Linux中国 荣誉推出

来源:https://linux.cn/article-2358-1.html

Python中import与from…import用法的不同之处

下面的内容主要介绍了Python中import与from…import用法的不同之处,欢迎大家参考:

在python用import或者from…import来导入相应的模块。模块其实就是一些函数和类的集合文件,它能实现一些相应的功能,当我们需要使用这些功能的时候,直接把相应的模块导入到我们的程序中,我们就可以使用了。这类似于C语言中的include头文件,Python中我们用import导入我们需要的模块。

eg:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import sys

print('================Python import mode==========================');

print ('The command line arguments are:')

for i in sys.argv:

    print (i)

print ('n The python path',sys.path)

from sys import argv,path  #  导入特定的成员

print('================python from import===================================')

print('path:',path) # 因为已经导入path成员,所以此处引用时不需要加sys.path

如果你要使用所有sys模块使用的名字,你可以这样:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
from sys import *

print('path:',path)

从以上我们可以简单看出:

############################

#导入modules,import与from...import的不同之处在于,简单说:

# 如果你想在程序中用argv代表sys.argv,

# 则可使用:from sys import argv

# 一般说来,应该避免使用from..import而使用import语句,

# 因为这样可以使你的程序更加易读,也可以避免名称的冲突

###########################

Python中import与from…import用法的不同之处就是这样,欢迎大家参考。。。。