One-line Linux CLI to remove span tag

Some CMS are too smart to handle <span> tag properly.

I have to copy the content into clipboard, remove the span tag, and paste it back into CMS.

Actually all the trouble could be saved by one line linux command,

xclip -o|sed 's%</span[^>]>%%g'|xclip -selection c

Linux桌面使用之道

作者: 陈斌(redguardtoo)

注意: 我会长期维护本文,请参考下面的更新时间

更新时间: <2016-10-09>

原创时间: <2011-05-08>

这是为有志于成为高手的中级Linux用户而写的入门指导.

1 哲学

1.1 长期投资

软件对我而言是长期投资.所以我会花很多时间学习软件的快捷键(快捷键长期来说操作比鼠标高效),那种只能用鼠标操作的软件对我来说就是"坏"软件.

1.2 理性思维

以文件管理器来说,在Windows平台下我长期使用并热爱Total Commander,在Linux下平台下也有几款文件管理器在界面和功能上和Total Commander上非常接近,自然从感情上讲我会爱屋及乌.但是我最后还是选择了以Emacs作为主要的文件管理器,以丑陋的Midnight Commander为辅助,因我已确定选择软件的总的原则是尽可能用少的的软件做尽可能多的事.具体说来就是以Emacs做任何事,如果一定要用其他软件辅助Emacs,快捷键也应是Emacs的.Midnight Commander符合该条件

1.3 科学方法

细节见后文,我要强调的是我的工具和方法都是有高手验证过,有官方文档支持.对我而言,科学的含义,就是前人反复验证过的,过去100%成功也许能保证现在将来可能成功(因工具环境不断在变化,所以只是有可能).除此以外都不叫科学.

1.4 以人为本

在后文我会列出一些筛选软件的方法.也会推荐一些软件.但你决不要认为只要用了这些软件或者记住了我的方法就能成为高手了.这只是敲门砖而已.

实际上我推荐的不是软件,而是人.这些软件和用户和开发者是一个精英荟萃的圈子.重要的是跟对人.

2 少而精

软件数量少,品质高,功能强,依赖小,界面通用.

2.1 数量少

很重要,只有用的软件少(但是完成工作不少),才能有精力精通.

软件少的另一好处是维护省心,例如找出多个软件快捷键冲突和在安装软件数量有关系.

2.2 品质高

实质很简单,就是:

  • 久经考验(例如Emacs的开发历史有35年以上)
  • 聪明人认同

何为久经考验,何为聪明人,是可找出客观指标.指标越严格,筛选结果就越少.

2.3 功能强

原谅我又用Emacs举例,它可以看网页,收邮件,写程序,做笔记,写博客.

功能强的终极境界就是提供了一个无所不能的可编程平台.

2.4 依赖小

例如,命令行软件不依赖于QT,GTK之类图形界面库,安装包小很多,运行时消耗内存也小,启动快.

2.5 界面通用

例如,我写程序用emacs,一般操作用bash shell,上网用Firefox,但是通过适当的设置(Firefox需要安装插件keysnail,其他软件只要用最新版即可),他们的快捷键都是Emacs的.

3 软件推荐

3.1 编辑器

我用Emacs,考虑到它可以做任何事,可以认为它是轻量级的.

Vim也用,万不得已用nano,结束了.

3.2 浏览器

Firefox.它是自由软件,所以有很多顶尖Geek为其写插件.例如keysnail可以把Firefox的快捷键设置为Emacs的快捷键.所以我可以不用鼠标浏览网页.

3.3 Shell

我用bash,在我的.bashrc中有如下一行,

export HISTSIZE=200000

确保我输入的所有命令都不会丢失,我偏爱命令行软件,但是记命令会消耗我很多脑细胞,所以我让shell替我记住.我只要记住按Ctrl+R可搜索历史就好了.

其他有用的选项还很多.这只是个例子,说明Bash是可编程的.

3.4 桌面

Gnome是不考虑,用轻量级的i3.

i3是平铺桌面(例如左窗口写代码,右窗口看PDF文档),学习曲线低.

3.5 其他

  • 联网自己写脚本,因为GUI工具如wicd之类的依赖多
  • 听音乐用命令行工具mpd和mpc
  • 播放视频用mplayer(命令行),等等.
  • 硬盘清理用bleachbit(清理常用软件产生的临时文件),localepurge(删除无用的多国语言),ncdu(检查硬盘占用)

4 软件使用也需维护

安装软件在包管理系统的帮助下很简单.麻烦的是最新软件有时候不稳定,这通常是因为软件的配置文件更新引起的.

4.1 将/etc目录下的默认配置文件备份

Linux的软件默认配置文件在/etc/目录下. 我使用分布式版本控制软件git管理/etc目录,分布式版本控制系统好处很多,最大好处就是数据到处有完整备份,非常安全.具体细节请参考wikipedia.

在Linux上更新完系统或者安装最新软件包后,可以考虑手动将/etc目录下的文件用git备份.

sudo git add /etc/
sudo git commit -am "backup"

一旦某软件不正常,可检查其/etc下默认配置文件的修改纪录,将配置文件恢复到上一正常版本.

sudo git log /etc/mysql/my.cnf #check history
sudo git checkout commit_ref(version) /etc/mysql/my.cnf #restoren file

4.2 将用户目录下的用户定制配置文件备份

我也用git将配置文件(在/home/username/下)备份到github的服务器上.这里必须用第三方服务器同步配置,因为我使用多台电脑.

具体操作不展开了.

4.3 将软件版本降级

最新版本的软件可能不稳定,这时降级是必要的.

对于Arch Linux来说很简单,请参考Archwiki,实际上很简单,安装名为downgrade的软件,然后让它干所有的体力活就行了.

packer downgrade

对于其他主流Linux发行版如Centos或者Ubuntu来说,由于测试周期长,不会有不稳定的问题.

小众版本(我用Gentoo Linux)策略是不随意用最新版本的软件.

4.4 云备份

多媒体文件用云备份服务更好,我推荐Dropbox.

顺便说一下,国内的服务不要用,安全原因,不言自明.

4.5 备份操作系统

不用经常作,又有云备份,又有分布式版本控制系统,怕什么.

备份整个硬盘是用Clonezilla,只是备份操作系统的话用以下命令,

tar zcvpf mylinux.tgz --exclude=/proc/* --exclude=/lost+found --exclude='mylinux.tgz' --exclude=/mnt/* --exclude=/home/username/* --exclude=/sys/* /

我建议用前者,因为省事.

假设你采用clonezilla备份操作系统,我建议将/目录(操作系统目录)和/home目录放在两个分区内.

如果能够按照少而精的原则选软件的话,操作系统分区不需很大(8G足够了),目前我所占空间控制在3G左右(例子比较极端,因我netbook只有4G硬盘),这样clonezilla的操作就很快.

4.6 阅读官方文档

阅读官方和社区文档.

Ubuntu社区的特点用户多,少见的bug一般都会在该社区报告.缺点是其文档深度不够.

Arch Linux和Gentoo Linux的特点是用户一般水准较高,所以文档技术含量很高.

4.7 虚拟机的用处

我虚拟机软件使用VirtualBox,虚拟机为Windows XP,该操作系统我会定期更新安全补丁.软件只安装了IE和firefox.该操作系统我只用来操作网络银行.每次操作完毕,我会重置虚拟机状态到操作前的snapshot.

5 常用软件的诊断修复

即使用了上述做法,一年中也会有一次倒霉.就是某个版本软件出问题了.没人能帮忙,不能降级,改配置也没用,也没有可用的错误信息.

问题看起来很难,事实上5分钟就搞定.这往往是因为依赖的第三方库的版本出问题了.

比如说firefox不能启动,运行如下命令调试,

strace -o err.txt firefox

读一下err.txt就可以知道是哪个库出问题了.不需要任何编程知识的,猜加google就可以了.

知道哪个库文件出问题了(保险起见,ldd firefox确认一下).比如/usr/lib/libpng.so.14找不到,简单的解决办法是用另一个版本的库文件代替.

如果/usr/lib/libpng.so.15是存在的,我们可以用该库顶替libpng.so.14,

sudo ln -s /usr/lib/libpng.so.15 /usr/lib/libpng.so.14

通常这样就行了.

万一冒名顶替不行,我们就必须根据丢失的库文件查找需要安装的软件包.

以Arch Linux为例(其他发行版也有类似功能):

pkgfile libpng

pkgfile属于软件包pkgtools,所以你必须安装pkgtools,

packer -S pkgtools-git

6 系统启动失败的修复

解决方法很简单,用常见的Linux启动光盘启动,然后chroot,其作用是以指定目录作为操作系统根目录(root directory),然后以此根目录为基准建立一个新的环境.

细节请参考https://wiki.archlinux.org/index.php/Change_Root.

比如说我升级kernel后系统启动失败,而老的kernel没有备份,我可以光盘启动电脑,然后chroot,再使用上文所提的工具升级或者降级kernel.

7 书籍推荐

书籍 评论
Advanced Bash-Scripting Guide by Mendel Cooper 经典,其.bashrc模板很有价值
The Art of Unix Programming by Eric Steven Raymond 开拓思路,当八卦看,和编程关系不大
The Debian Administrator's Handbook 很好.捡有用的章节看

8 常见问题

等你的问题了.

9 联系我

这是我的twittergoogle plus,也可以通过我的email<chenbin DOT sh AT GMAIL DOT COM>联系我.

我的主力博客为http://blog.binchen.org.

用mintty作为cygwin的console

UPDATED: <2015-01-31 Sat>

CREATED: <2011-04-29>

cygwin1.7在我的电脑上不能显示中文,已困扰我很久了.

今天才找到解决办法,只要安装mintty即可.

最新版Cygwin默认就已安装启用mintty.

安装后在宽屏显示器上字可能较小, 解决办法如下:

  • 或参考其手册缩放字体.
  • 或右击左上角设置字体, "新宋体 常规 三号"

另外设置scroll back 80000行. 右侧滚动条无.

以下是我的cygwin.bat,

@echo off
set EDITOR=vi
set VISUAL=vi
REM shamelessly copied from git://github.com/justsoso8/dotfile.git
REM mintty installed which supports chinese
REM =======================================
@echo off
rem find cygwin roo directory one by one
rem disk c -> disk d -> disk e

:CYGWIN_C
if not exist c:\cygwin goto CYGWIN_D
set _cygwinroot=c:\cygwin
goto HAVECYGWIN

:CYGWIN_D
if not exist d:\cygwin goto CYGWIN_E
set _cygwinroot=d:\cygwin
goto HAVECYGWIN

:CYGWIN_E
if not exist c:\cygwin64 goto CYGWIN_F
set _cygwinroot=c:\cygwin64
goto HAVECYGWIN

:CYGWIN_F
if not exist d:\cygwin64 goto NOCYGWIN
set _cygwinroot=d:\cygwin64
goto HAVECYGWIN

:NOCYGWIN
echo no cygwin installation found on disk C/D/E/F
pause
goto EOF

:HAVECYGWIN

chdir %_cygwinroot%\bin
set _termapp=%_cygwinroot%\bin\mintty.exe
start %_termapp% -w full /bin/bash --login -i
:EOF
exit

坚持使用gnu screen

虽然tmux很优秀,但是目前很难支持cygwin(Nicholas Marriott在2010年12月说的),而我的工作需要使用windows.

最新版的screen的一个重要特性就是已支持垂直分屏,其快捷键为"C-a |".

要安装最新版的screen,在我的Arch Linux下很简单,

yaourt -S screen-git

在windows的cygwin下安装要多几步.

首先安装软件包libncurse-devel,然后去官方网站下载最新源代码包(目前版本为4.0.3),解压缩,

tar zxf screen-4.0.3.tar.gz

编译安装,

cd screen-4.0.3;configure;make;make install;

如用urxvt作为Terminal Simulator(比如我),直接启动screen会报错,

$ screen

$TERM too long - sorry.

原因为screen的开发者对于环境变量$TERM的最大长度做了不合理的假定.这里是具体讨论,解决办法很简单. 在.Xdefaults中添加一行,

urxvt*termName: rxvt-256color

在.screenrc中添加一行,

term rxvt-256color

使用screen前我将screen的Ctrl-a改为Ctrl-t

因为Ctrl-a在bash和emacs中都是常用快捷键,在.screenrc中添加一行,

escape"^Tt"  #the default of A interferes with emacs keybindings for terminal, and I never use the emacs transpose command

这个修改我是从Balaji S. Srinivasan.screenrc抄来的. 可以参考emacs wiki获得更多兼容emacs的设置.

奇客(Geek)的常用软件清单(OS X, Windows, Linux)

作者: 陈斌 (redguardtoo)

更新时间: <2016-10-09 Sun>

原创时间: <2011-04-16 Sat>

品味小众,如你用360/阿里巴巴/百度等免费软件套装,本文就不用看了.

我的标准是:

  • 功能强大(可编程,支持插件)
  • 性能优秀(不带图形界面,用C写的,一般性能还可以)
  • 诚实可靠(开源最好,闭源的话开发者要有相当信用)
  • 绿色软件,配置文件最好是纯文本

1 Windows软件清单

工作中我90%的时间用Cygwin+Visual Studio+Vim+Firefox.下班后基本不碰windows.

名称 说明 频率 性质
Cygwin Linux下常用工具集合 开源
7-Zip 压缩解压缩 开源
AviSynth 2.5 视频编辑 开源
CDBurnerXP 刻录 免费
CDex cd转mp3,自动生成文件名 开源
Ditto 剪贴板管理 免费
CMake 2.8 跨平台build工具,相见恨晚 开源
Comicsviewer 看漫画 免费
DAEMON Tools 虚拟光驱 免费
Wink 录屏 免费
Dependency Walker 检查dll依赖 免费
eMule p2p下载 开源
Foobar2000 音乐播放 开源
Gimp 图像编辑 开源
小狼毫输入法 输入法 开源
ClamWin 开源杀毒 免费
ImageMagick 命令行图像处理 开源
InfraRecorder 刻录 开源
Inno Setup 5 打包,开发用 开源
IPMsg 局域网通信 开源
IrfanView 看图,可与total commander集成 免费
Microsoft Visual Studio Express 2010 C++ IDE 免费
Firefox 网页浏览 开源
mtPaint mspaint的替代品,界面费解 开源
LibreOffice 字处理,doc转pdf,组织结构图 开源
OpenVPN VPN 开源
Pandora Recovery 恢复误删除的文件 免费
SumatraPDF PDF阅读器 开源
VirtualBox 虚拟机,网上银行用 开源
MiniThunder(迅雷) 下载 免费
UltraVNC 远程桌面控制 开源
Subtitle Workshop 字幕调整 免费
USBOOT 1.7 制作usb自启动盘 免费
Goagent 翻墙 开源
Vim/GVim 文本编辑 开源
Total Commander 世界第一的文件管理器 共享
bblean windows shell 开源
Bridge Base Online 游戏 免费
ntemacs 文本编辑 开源
openssl 如题 开源
Python2.7 一种脚本语言 开源
wxWidgets 3.0 跨平台c++ GUI库 开源
Mplayer 命令行视频播放软件 开源
autoruns 检查默认启动软件 免费
process explorer 检查运行程序 免费
Everything 找文件 免费

2 Linux软件清单

操作系统为Gentoo Linux.使用频率最高的为Git+Emacs+Vi+Firefox+I3+Bash. FirefoxThunderbird用的是绿色版本.

名称 说明 频率
Emacs 任何事
Vim 文本编辑
Firefox 网页浏览
Terminator Terminal
Bash shell
Percol 交互过滤文本
Scrot 截图
I3 窗口管理
Wine win32模拟器
Goagent 翻墙
Mplayer 视频播放
Ncmpcpp+mpc+mpd 音频播放
Amule (amule-dlp) p2p下载
Rtorrent BT下载
Virtualbox 虚拟机
Gimp 图片编辑
Git 版本控制
Zathura pdf阅读
Parcellite 剪贴板管理
Fcitx 中文输入
Libreoffice 办公软件
ThunderBird 电子邮件
Dunst 显示通知
Popfile 邮件分类

3 Mac软件清单

使用频率最高的软件为Emacs, Firefox, Bash, Adium.

名称 说明 频率
Emacs 任何事
Firefox 上网
Bash shell
Libreoffice 办公软件
迷你迅雷 下载
HomeBrew 开源软件包管理(少数几个亮点之一)
Flybuy 剪贴板管理
Mplayer X 类mplayer的轻量级视频播放器
VLC 视频播放器,字幕支持好
Monolingual 删除没用的语言和
Skim 看PDF
CCleaner 清理系统垃圾
有道词典 查单词
Chicken of the VNC vnc客户端(远程桌面)
IPMessenger 局域网内通信传文件
Adium 即时通信

4 某些优秀软件的配置

4.1 Firefox

插件名称 说明 频率
Adblock Plus 过滤广告,支持正则表达式
KeySnail 安装了HoK脚本
ImageBlock (or Picture Blocker) 和图片说再见
ColorZilla 取色
Vacuum Palaces Improved firefox数据库加速
Magrent 转换链接为torrent文件
MozRepl 和Emacs交互,前端开发必备
Greasemonkey js脚本操作firefox
MeasureIt Firefox的尺子
QR Code Image Generator 产生QR码
JSONView View JSON
LeechBlock 自绝于社交网络
Tile Tabs 子窗口
ePub-Catalog epub图书管理
Fireinput 拼音输入法
Nimbus Screen Capture 网页截屏

4.2 ThunderBird

原生支持Gtalk.

插件名称 说明 说明
EmailPicky 收集邮件地址 右击, Pick email IDs from this folder
Lightning Calendar 右击, new calendar
Mail Redirect redirect mail 不回信给你

4.3 Greasemonkey

需刷新网页使script生效

插件名称 说明 频率
NinjaWebCoder 从网站拷贝代码
眼不见心不烦 清理weibo.com

4.6 Total Commander

插件名称 说明 频率
CatalogMaker.wcx 创建文件列表
CHMDir.wcx 生成chm文件
7zip.wcx 压缩解压缩7zip格式的压缩文件
UnInstTC.wfx 管理"添加/删除软件"面板
Registry 管理注册表
ex2fs.wfx 访问linux分区(只读)
sftpplug.wfx 支持sftp
imagine.wlx 看图

Hello Word

    Tags : 

这是第一篇。用org2blog发的,看一下中文支持如何.

用org2blog+emacs发表博客

我有兴趣开始写博,完全是因为我开始爱上emacs,以至有人说emacs的插件org2blog使的写博客非常高效,我就想试试.

我(计划)把所有的文章都放在一个org文件里(BTW,我爱死org-mode了,它本来是做计划管理和日志的,但事实上是无所不能),然后post sub-tree:

M-x org2blog/wp-post-subtree

要正常使用org2blog,必需安装最新的org-mode(我的版本为7.5,`M-x org-version'检查当前版本,警告,7.5不可靠,应升级到最新版本,我用从git服务器取得"d6aba4db"版本).

emacs(版本23.3.1)自带的org-mode太老,和最新的org2blog(<2011-04-12 二>的版本)不兼容.

org2blog安装步骤在上文的链接里都有,也可以参看Blogging with org2blog.

org-mode安装步骤见官方文档.

切.格瓦拉 阿根廷(Che: Part One),一部无聊的政治宣传片

剧情基本上就是记流水帐,从1955年卡斯特罗(Castro)等人在墨西哥城组织七·二六运动(26th of July Movement)开始,然后就是行军,袭击兵营,伏击战,救治伤员,做群众工作(给村民看病,演讲),处决违法军纪的士兵,最后是革命的高潮,切.格瓦拉(Che Guevara)和Camilo Cienfuegos夺取Las Villas省的首府Santa Clara,这是古巴革命最后一场战役,12小时后古巴独裁者巴蒂斯塔(Batista)离开了古巴. 当中穿插了卡斯特罗访问美国,在联合国做演讲,接受采访的片段.

电影的主要缺点是缺少人物性格刻画.格瓦拉的政治主张是什么(例如建立什么样的政府?)?他为何接受社会主义?他喜欢什么?不喜欢什么?他的性格有什么特点(不愿意在阿根廷做医生而去古巴参加革命的人很可能性格有不同于常人的地方)?这些电影中都没有提及.我看到的只有好人打坏人再加上一些战斗场面.

古巴政府和军队坏,因为电影中古巴革命者说Batista腐败.说古巴政府出卖国家利益给美国,例如古巴对美国的贸易逆差为10亿美元.还因为一些比较感性的镜头,比如古巴军队枪杀帮助游击队的平民.古巴军队的飞机轰炸攻入城市的革命者,杀伤了很多平民.古巴军队虐待俘虏.

说实话我认为这种对坏蛋的描写挺幼稚的.我感兴趣的是古巴革命爆发和革命队伍壮大的原因,对此电影没有做出合理的解释.

例如所谓古巴和美国的贸易逆差,我也可以从经济学解释为古巴需要从美国进口的货物多,可以出口给美国的美国人需要的货物少,这好像恰恰是"美国是世界最强大的发达国家的"的结果.当然"贸易逆差"可以是激发"民族主义"的借口,民族主义几乎是近现代革命的必备导火索.但是"贸易逆差"的这段戏导演仅处理为几个领袖间的闲谈,给我的印象就是领袖们私下的谈话缺乏逻辑思维,如果是通过给群众或士兵的演讲来表现的话,我就会认为卡斯特罗等人确实挺会激发(或操纵)大众的情绪.

电影中描写古巴军队残忍的场景很平庸,例如有一幕是一个平民跑来见格瓦拉,要求其部下离开他家,因为政府军要是发现叛军,会认为他通敌,把他全家杀死.我的理解是,从逻辑上来讲,这段镜头说明了政府军的反游击队战术很成功.如果导演想说明政府军是非正义的话,至少这和古巴革命没什么关系,因为在革命和战争中清洗通敌嫌疑分子是很常见的,是内战导致了清洗而不是反之.

其他类似场景我就不罗嗦了,本质上都一样,内战中常见的残酷行为如果一边倒地都列在政府军的头上,感觉太假了,没有说服力.而且这些行为古巴革命没有重要的因果联系(同样的事件也发生在美国,英国,法国,俄国内战上).

对好人的描写我怀疑是参考了我国早期的革命电影.电影的一开始,古巴军队在追捕逃亡的格瓦拉,导演拉了个惊慌失措的普通战士给格瓦拉作伴来衬托主角的镇定自若.接下,格瓦拉免费给村民看病,格瓦拉教文盲战士识字,格瓦拉英明神武,某个战士连发两发火箭炮都没有打中敌人的据点,格瓦拉说声"让我来",夺过火箭炮一炮就打爆敌人据点.等等等等...

电影唯一的亮点是战争场面不错,挺火爆残酷的,我作为男性观众挺享受的.
Technorati Tags: , , , ,

DropBox很有创意

本质上是给你一个网络硬盘还带版本控制.但是把界面傻瓜化了,用户看到的就是在My Document目录下多了个My DropBox文件夹,然后往里丢东西就可以了.使用这个链接可以立刻免费获得2G空间.


perl code to change ip

I write this script for a real project. It changes ip of every node in a local network. All the information related to our customer is deleted.

if you see the test() function and you will notice "assert" lines. Yes, I believe in TDD (Test Drivern Development).


#!/usr/bin/perl
require "assert.pl";
if(0){
open(F,"/etc/hosts");
@lines=;
close(F);
foreach (@lines){
    print $_;
}
}#if(0)

############################
# main
############################
if(1){
if(&is_interactive()){
    print "Usage: echo 127.0.0.1 ekcms| ./chgip\n";
    exit 1;
}

$pipein=;
chomp($pipein);
my $h=&who_will_change($pipein);
foreach (keys %$h){
    print "key=$_;val=$h->{$_}\n"; #debug
}
&change_etc_hosts("/etc/hosts",$h);
#distribute /etc/hosts 
foreach my $k (keys %$h){
    system("scp /etc/hosts root@$k:/etc/hosts") || assert(0);
}
&change_ip("/etc/sysconfig/network-scripts",$h);

}#if(0)

############################
# test
############################
if(0){
    &test();
}#if(0)

############################
# subroutines
############################
sub test
{
if(0){
    print &unique_id();
}#if(0)

if(1){
    my $p="127.0.0.1 ekcp1\n0.0.0.0 ekcp2";
    $p.="\n99.99.99.99 ".`hostname`;
    my $h=&who_will_change($p);
    foreach (keys %$h){
        print "key=$_;val=$h->{$_}\n"; #debug
    }
    &change_etc_hosts("hosts",$h);
    #&change_ip("./",$h);
}#if(0)
}

sub is_interactive {
    return -t STDIN && -t STDOUT;
}


# Usage: my $p="127.0.0.1 ekcp1\n0.0.0.0 ekcp2";$h=&chgip($p);print $h->{'ekcp1'};
sub who_will_change
{
    my $p=shift;
    my %h=();
    my @ls=split(/\n/,$p);
    foreach (@ls){
        chomp($_);
        if($_ eq ""){next;}
        my @a=split(/ /);
        if($a[1] eq ""){next;}
        $h{$a[1]}=$a[0];
    }
    return \%h;
}


# Usage: my $p="127.0.0.1 ekcp1\n0.0.0.0 ekcp2";$h=&chgip($p);&change_etc_hosts("/etc/hosts",$h);
sub change_etc_hosts
{
    my $f=shift;
    my $h=shift;
    open(F,$f);
    @lines=;
    close(F);
    foreach my $k (keys %$h){
        #print "k=$k\n"; #debug
        my $replaced=0;
        for(my $i=0;$i<=$#lines;$i++){
            if($lines[$i]!~/^[\d\.]+[\s]+$k\W/){
                next;
            }
            $lines[$i]=~s/^[\d\.]+/$h->{$k}/g;
            $replaced=1;
            #print "line=".$lines[$i]; #debug
        }
        if(!$replaced){
            push(@lines,"$h->{$k} $k\n");
        }
    }
    foreach (@lines){print "line=$_";}; #debug
    open (F,">$f");
    print F (@lines);
    close(F); 
}

#Usage: my $p="127.0.0.1 ekcp1\n0.0.0.0 ekcp2";$h=&chgip($p);&change_ip("/etc/sysconfig/network-scripts",$h);
#Return: 0 - everything ok; 1 - several hosts unreachable
sub change_ip
{
    my $dir=shift;
    my $h=shift;
    my $ret=0;
    #print "dir=$dir\n"; #debug
    my $pingcmd="ping";
    my $s=`uname`;chomp($s);
    if($s eq "Linux"){ $pingcmd="ping -c 2"};
    $s=`hostname`;chomp($s);
    foreach my $k (keys %$h){
        #if(system("$pingcmd $k")!=0){
        #   $ret=1;
        #   next;
        #}
        if( $s eq $k){ #local
            print "s=$s;k=$k\n"; #debug
            system("perl -i.bak -pe 's/IPADDR=.*/IPADDR=$h->{$k}/g' $dir/ifcfg-eth0") || assert(0);
        }
        else{ #remote
if(0){
            my $u=&unique_id();
            system("scp root@$k:$dir/ifcfg-eth0 /tmp/$u.ifcfg-eth0") || assert(0);
            system("perl -i.bak -pe 's/IPADDR=.*/IPADDR=$h->{$k}/g' /tmp/$u.ifcfg-eth0")|| assert(0);
            system("scp /tmp/$u.ifcfg-eth0 root@$k:$dir/ifcfg-eth0 ")|| assert(0) ;
            system("/etc/init.d/network restart")|| assert(0);
}#if(0)
        }
    }
    return $ret;
}

sub unique_id()
{
    my $s=`date +%s`;
    return crypt($s,chr(int(rand(127))));
}


############################
# test data
############################