环境:SpringMVC 3.2.16,JUnit 4.12
引用WEB-INF/lib目录下的jar包
项目里有些jar包没有在repository里,又需要引用。
环境:SpringMVC 3.2.16,JUnit 4.12
项目里有些jar包没有在repository里,又需要引用。
我常用的工具软件,Windows平台,整理如下。
在实施SpringMVC项目过程中,会遇到一些常见设计问题,这里总结一下。
按官方文档NutchTutorial安装Nutch 1.11
下载的.tar.gz解压到/usr/share目录下。
nutch 1.x支持solr 4.x(来源),官方教程也是对应solr 4.x的,所以先下载solr 4.10.4来用。
注1:NutchTutorial里有几处对schema.xml文件的修改(EnglishPorterFilterFactory等等),在nutch 1.11里已经改好了,不再需要。
注2:NutchTutorial最后部分bin/nutch solrindex命令的最后一个参数crawl/segments/,经试验应为crawl/segments/*,否则会提示找不到文件错误。
启动solr内置的jetty服务器,命令:
java -jar start.jar
然后在浏览器里访问下面的地址即可管理solr:
在浏览器里可以使用下面的链接执行查询(即solr API):
http://localhost:8983/solr/collection1/select?q=mykeyword&wt=xml&indent=true
注:如果Solr用5.4版本的,启动命令是(Nutch的文档里example/start.jar是5.2以前的solr启动方式):
bin/solr start -e cloud -noprompt
Nutch2与Solr5的集成方式在官方文档里没有详细描述,solr5的目录结构与solr4不一样(没有collection1),以下文章可参考:文章1
为支持中文分词,我们使用mmseg4j项目。
从github上的mmseg4j主页下载2.3.0版本,解压后得到两个.jar文件,放在 /usr/share/solr-4.10.4/example/solr-webapp/webapp/WEB-INF/lib/ 目录下,并在schema.xml里加入mmseg4j的field types。
注意:要特别注意mmseg4j与solr的版本匹配,在mmseg4j的下载包里有说明,针对solr 4.9和4.10要使用mmseg4j的2.2.0版本。如果使用了mmseg4j 2.3.0版,分词时会提示java.lang.RuntimeException: java.lang.AbstractMethodError异常。
按官方文档进行到ant runtime命令时有两个问题:1)需要等比较久且一开始的几分钟内没有进度;2)可能会警告找不到tools.jar文件,只要yum安装java-1.7.0-openjdk-devel即可(注意不要用java 1.6,版本过低会导致编译失败),JAVA_HOME环境变量在/etc/profile里指定,执行source /etc/profile以便不重启生效。
进行到bin/nutch inject urls这一步时可能会报一些找不到类异常或VerifyError错误,一般是由于nutch与hbase里一些jar包版本不一致造成的,解决方法是用hbase里的jar代替nutch里的相应jar包。主要是$hbase_home$/lib目录下的hbase*.jar、hadoop*.jar、htrace*.jar和protobuf*.jar,复制到$nutch_home$/runtime/local/lib目录下,注意先移除旧的jar包。
遇到一个不好解决的问题:ava.lang.IncompatibleClassChangeError: Found interface org.apache.hadoop.mapreduce.TaskAttemptContext, but class was expected。仔细又看了官方文档,与Nutch2配套的hbase建议是hbase-hadoop(没写hadoop1或hadoop2,原来是指hadoop1,虽然hbase的quickstart里说大部分情况用hadoop2:“in most cases, you should choose the file for Hadoop 2”),之前我是按hadoop2下载的,改为hadoop1环境即可。
改为hadoop1后,nutch inject可以正常执行了,但nutch generate时遇到java.lang.NoSuchMethodError: org.apache.hadoop.hbase.HRegionLocation.getServerAddress()异常。问题应该是gora-hbase版本,在ivy.xml里改为0.6.1,重新ant runtime,发现build出来的hbase相关的jar包自动都升级为0.98了(之前ivy.xml里是0.5,对应0.94),而且包文件名都带hadoop2!然后inject时又报java.lang.IncompatibleClassChangeError: Found interface org.apache.hadoop.mapreduce.Counter, but class was expected异常(在hadoop.log里看)。
待参考:http://www.cnblogs.com/mactech/p/4229708.html http://stackoverflow.com/questions/26236112/hadoop-2-5-1-nutch-2-2-1-found-interface-org-apache-hadoop-mapreduce-taskatte
再次查看官方文档,发现其中的nutch2下载链接有变化(也许是我记错了),以前我下载的是nutch 2.3,现在指向的是nutch 2.3.1。下载2.3.1后查看ivy.xml发现gora版本是0.6.1(nutch 2.3时对应gora 0.5),且hadoop对应2.5.2(nutch 2.3时对应hadoop 1.2.0)。重新用nutch 2.3.1按官方文档,配合hbase-0.98.8-hadoop2,所有问题解决。
solr5引入了configset的概念,所以schema.xml文件的位置与solr4有所不同。
nutch-site.xml配置文件说明:见此链接
nutch2.3.1使用crawl命令时提示“No IndexWriters activated - check your configuration”错误,解决方法是在nutch-site.xml里添加plugin.includes属性,详见此链接。
nutch2.3.1里solrindex被index取代,指定solr地址改为-D solr.server.url=xxx,例如bin/nutch index -D solr.server.url=http://localhost:8983/solr 1453805148-685784700 -crawlId crawl2
nutch2.3.1的parse步骤提示“http://news.sina.com.cn/ skipped. Content of size 130163 was truncated to 65536”,在nutch-site.xml里设置http.content.limit为-1。(nutch-default.xml里可以看到所有可设置的项)
nutch2.3.1的updatedb步骤耗时过长:查看logs/hadoop.log发现无法连接到hbase在一直重试,不知道什么原因hbase停止了,$HBASE_HOME$/bin/start-hbase后updatedb继续完成。
nutch2.3.1的fetch步骤控制台里显示“... 500 URLs in 2 queues”,实际队列里的url数量超过500但无法显示,原因见这个链接。
注意:两个配置文件regex-normalize.xml和regex-urlfilter.xml起作用是有先后的,normalize在前,所以filter时用来匹配的url是经过normalize的。例如http://my.website.com/product/38392/?from=mobile这样一个url,在normalize步骤有可能已经变成了http://my.website.com/product/38392/。这两个配置文件里使用的正则表达式遵守Perl5语法。
seed.txt里的url可以用"#"注释
删除solr里已索引的文档:
curl http://localhost:8983/solr/collection1/update --data-binary "<delete><query>\*</query></delete>" -H 'Content-type:text/xml; charset=utf-8'
curl http://localhost:8983/solr/collection1/update --data-binary "<commit/>" -H 'Content-type:text/xml; charset=utf-8'
使用bin/crawl脚本抓取时,发现regex-urlfilter.txt没起作用,原因是bin/crawl脚本里的generate命令加了-noFilter参数,去掉后解决。
通过solr-index命令导入solr的文档,tstamp字段值都是"1970-01-01T00:00:00Z"。根据nutch用户组里的讨论,tstamp字段应该是抓取网页的时间,不应该为空(1970)。但检查了solrindex-mapping.xml文件,里面tstamp字段的stored参数值已经是true。暂时的解决方案,在nutch-site.xml的plugin.includes里添加index-more插件,这样在solr索引的每个文档里会多出date、contentLength等若干个新字段,其中date字段可用于表示文档的抓取时间。
Nutch常用参数
1、同一服务器两次抓取间隔:nutch-site.xml里fetcher.server.delay
2、只抓取站内链接:nutch-site.xml里db.ignore.external.links
3、从页面里最多解析出多少个链接:nutch-site.xml里db.max.outlinks.per.page
由于磁盘空间占满,扩容后hbase无法正常启动。查看$hbase_home$/logs/后发现ERROR master.HMasterCommandLine: Master exiting / java.io.EOFException at ...readInt,看起来像是zookeeper在读取数据文件时报的错误,可能是之前的非正常停止导致数据文件损坏,于是在$hbase_home$/conf/hbase-site.xml配置文件里将hbase.zookeeper.property.dataDir指向另一个新建的目录,再start-hbase恢复正常。
有用链接:HBase集群安装过程中的问题集锦
在name节点上
首先配置hadoop,主要参考Hadoop: Setting up a Single Node Cluster,按Pseudo-Distributed Operation配置。
1.下载hadoop-2.7.2/hadoop-2.7.2.tar.gz并解压缩到/usr/share/目录下
2.编辑/etc/profile文件,在结尾处添加export $HADOOP_HOME=/usr/share/hadoop-2.7.2和export PATH=$PATH:$HADOOP_HOME/bin这两句,以便nutch脚本可以找到并执行hadoop。
3.编辑$HADOOP_HOME/etc/hadoop/hadoop-env.sh,将JAVA_HOME指到java安装目录(即使在/etc/profile里已经有JAVA_HOME,这一步也不能省略)
4.通过访问http://localhost:50070/可看到dfs信息
5.设置hbase-site.xml让hbase使用hdfs:
<property>
<name>hbase.cluster.distributed</name>
<value>true</value>
</property>
<property>
<name>hbase.rootdir</name>
<value>hdfs://cluster1:9000/hbase</value>
</property>
如果启动hbase时提示找不到JAVA_HOME,修改hbase-env.sh脚本。
6.修改yarn-site.xml:
<property>
<name>yarn.resourcemanager.hostname</name>
<value>cluster1</value>
</property>
<property>
<name>yarn.nodemanager.aux-services</name>
<value>mapreduce\_shuffle</value>
</property>
在data节点上:
1.安装hadoop,步骤和name节点上相同。
2.将name节点的authorized_keys文件scp到data节点,确保name节点可以不用密码ssh到data节点
3.将name节点的几个配置文件复制到data节点相同目录下:
scp /usr/share/hadoop-2.7.2/etc/hadoop/core-site.xml root@cluster2:/usr/share/hadoop-2.7.2/etc/hadoop/core-site.xml
scp /usr/share/hadoop-2.7.2/etc/hadoop/hdfs-site.xml root@cluster2:/usr/share/hadoop-2.7.2/etc/hadoop/hdfs-site.xml
scp /usr/share/hadoop-2.7.2/etc/hadoop/mapred-site.xml root@cluster2:/usr/share/hadoop-2.7.2/etc/hadoop/mapred-site.xml
scp /usr/share/hadoop-2.7.2/etc/hadoop/yarn-site.xml root@cluster2:/usr/share/hadoop-2.7.2/etc/hadoop/yarn-site.xml
4.在name节点的/etc/hosts里添加data节点的ip,例如“10.0.0.2 cluster2”,否则data节点可能会无法连接到name节点(“Datanode denied communication with namenode because hostname cannot be resolved”)
5.在name节点的$HADOOP_HOME/etc/hadoop/slaves里添加data节点的ip地址
6.(如果执行job时提示找不到HBaseConfiguration等异常,说明.job文件里缺少相应的jar包),用下面的方法重新打包:
cd runtime/deploy
unzip -d apache-nutch-2.3.1 apache-nutch-2.3.1.job
rm apache-nutch-2.3.1.job
cd apache-nutch-2.3.1
rm lib/hbase-\*\*\*.jar
cp /usr/share/hbase-0.98.8-hadoop2/lib/hbase-common-0.98.8-hadoop2.jar lib/
cp /usr/share/hbase-0.98.8-hadoop2/lib/hbase-client-0.98.8-hadoop2.jar lib/
cp /usr/share/hbase-0.98.8-hadoop2/lib/hbase-protocal-0.98.8-hadoop2.jar lib/
zip -r ../apache-nutch-2.3.1.job ./\*
cd ..
rm -r apache-nutch-2.3.1
补充:还要修改deploy里nutch-site.xml、hbase-site.xml,并打到.job包里。
7.在hdfs上创建种子列表目录
hdfs dfs -mkdir /urls
hdfs dfs -put seed.txt /urls
参考:
Running Nutch in (pseudo) distributed-mode (Nutch1.x)
INSTALL HADOOP+HBASE+NUTCH+ELASTICSEARCH
验证hadoop
hadoop自带了一些示例应用,可以用于验证hadoop集群是否正常,以wordcount为例:
hdfs dfs -mkdir /wordcount
hdfs dfs -mkdir /wordcount/input
#编辑一个本地文件test.txt并输入一些单词或短语,例如hello word,每个占一行
vi test.txt
#输入内容(略)
hdfs dfs put test.txt /wordcount/input
#/wordcount/output目录必须“不存在”,否则会报错
hadoop jar $HADOOP\_HOME/share/hadoop/mapreduce/hadoop-mapreduce-examples-2.7.2.jar wordcount /wordcount/input/\* /wordcount/output
#查看hdfs上生成的结果
hdfs dfs -ls /wordcount/output
hdfs dfs -cat /wordcount/output/part-r-00000
另:集群里每台机器的hostname最好与/etc/hosts文件里所用的保持一致。
遇到的问题:
1、org.apache.zookeeper.ClientCnxn: Opening socket connection to server localhost/127.0.0.1:2181. Will not attempt to authenticate using SASL (unknown error)
解决:查看datanode上的$HADOOP_HOME$/etc/hadoop/logs/yarn-root-nodemanager-xxx.log文件,发现org.apache.hadoop.ipc.Client: Retrying connect to server: 0.0.0.0/0.0.0.0:8031的错误信息。参考这个帖子,在datanode的yarn-site.xml里添加了yarn.resourcemanager.hostname属性,0.0.0.0异常消失,但无法连接到2181端口问题依旧。后检查发现master上的hbase-site.xml有两个,其中一个在/usr/share/hbase-xxx目录下,另一个在nutch/runtime/deploy里,前者里没有配置hbase.zookeeper.quorum属性,添加后重启hbase问题解决(另外还添加了一个hbase.master属性值为master:60000)。
网站内容抽取
可采用boilerpipe,一个开源的基于训练的内容抽取库。或采用针对每个网站分别定制的方案,参考链接1
支持js加载
自定义如何Parse所抓取到的网页
使用ParsingFilter和IndexingFilter,参考链接
Solr的查询语法很丰富,通过组合各种参数可以达到多种查询目标,官方文档可通过这个链接下载(pdf格式):Apache Solr Reference Guide
限定在指定日期范围内的文档里搜索:fq=date:[2016-02-15T00:00:00Z TO 2016-02-15T23:59:59Z]
要进行分组统计,使用facet参数,例如统计最近30天内指定关键词出现次数(注意:网上有些资料使用facet.date,这个参数已经在solr 3.1以后deprecated了,用facet.range替换):facet=true&facet.range=date&facet.range.start=NOW/DAY-31DAY&facet.range.end=NOW/DAY&facet.range.gap=%2B1DAY (%2B是URL encode后的加号)
以下环境为Android Studio 1.3.2,Gradle 2.7(as自带2.4,单独下载的2.7)
新浪微博提供的SDK里所带的weibosdkcore.jar里包含了BuildConfig类,而api工程也会生成同名(包名也相同)类,所以有此编译异常。解决方法是用工具(如7zip)直接删除weibosdkcore.jar里的BuildConfig.class文件。还有其他解决方法,这个链接不错。
有时clean后仍然有文件残留(例如classes.jar),此时需要手工删除项目路径下的build目录(删除时可能会提示classes.jar被占用,多半是as自己在使用,可关闭as再重试)。比较恶心的是,clean时并不会提示你有文件无法删除。
假设自己写了一个android library(名称library1),然后想在Project1和Project2里都使用它,但不把library1复制两份。窍门是在project2的setting.gradle文件里像下面这样引用project1里的资源:
include ':../project1/library1'
检查settings.gradle文件里,include的module是否存在,通常是include了不存在的module造成的。参考链接
多个module依赖多个相同的jar文件时会有这个问题,我当时遇到的是xutils,解决办法是在jcenter上找到了对应的repository,改为不直接使用jar而是使用repository解决。Proguard Troubleshooting
在build.gradle里指定项目proguard配置文件时,用proguardFiles可以同时指定多个,用proguardFile可指定一个(可多行),经测试效果是一样的。注意:在module settings对话框里可能会显示不出来正确的文件名。还有一个变化:比较新的as版本缺省文件名是proguard-rules.pro,以前是proguard-rules.txt。
例如module A依赖module B和module C,在Eclipse里运行时B和C里BuildConfig.DEBUG的值会是true(导出签名apk后会自动变成false);然而在Android Studio里B和C里的BuildConfig.DEBUG值总是false,A里的正常。这样就导致if(BuildConfig.DEBUG){Log.d(...)}日志无法正常显示。参考链接 参考链接2
一次Eclipse发生内存溢出(ADT环境,多打开几个xml文件内存占用就会飚升),强制结束任务,再次启动Eclipse发现闪退。
本文记录在使用WordPress过程中的问题和解决。
安装过程比较顺利,没有遇到大问题。安装环境是CentOS 6.5(DigitOcean的CentOS7 image里默认的yum源没有mysql-serve比较奇怪),安装步骤如下:
yum install httpd mysql-server mysql php php-mysql
wget https://wordpress.org/latest.tar.gz
tar zxvf latest.tar.gz
mv /root/wp/wordpress /var/www/html
修改/etc/httpd/conf/httpd.conf
配置文件,添加域名配置:
ServerName www.mydomain.com
并在文件最后增加下面的设置:
<VirtualHost \*:80>
DocumentRoot /var/www/html/wordpress
ServerName www.mydomain.com
</VirtualHost>
如果有多个<VirtualHost>
,需要在httpd.conf
里启用下面这个配置:
NameVirutalHost *:80
service httpd start
service mysqld start
> create database wordpress;
> grant all privileges ON wordpress.* TO 'username'@'localhost' identified by 'mypassword' with grant option;
> flush privileges;
此时可以在浏览器里访问http://www.mydomain.com
进入wordpress的安装向导,并按向导完成剩余的设置工作。
可手工在wordpress目录下建立此文件。
上传图片提示Unable to create directory wp-content/uploads/2014/11. Is its parent directory writable by the server?
或无法建立目录wp-content/uploads/2014/11。有没有上级目录的写权限?
试了网上一些办法没起作用,实际试验下来这样解决:
1) 在wp-content下建立uploads
目录,并执行“chown -R nobody:nobody uploads”;
2) 将wp-content和wp-content/uploads的权限全部设置为777(不建议)。
这也是由于权限不正确引起的,解决方法是将wordpress所在目录的所有者设为apache(在有些系统里可能是www):
chown -R apache:apache /var/www/html/wordpress
通过安装插件,用国内镜像字体网址替代google字体网址。参考链接
主要命令如下:
git clone -b v1.2.stable git://git.freeswitch.org/freeswitch.git
cd freeswitch/
./bootstrap.sh && ./configure && make && make install && make hd-sounds-install && make hd-moh-install && make samples
最后一个命令大约执行20分钟
缺省安装目录:/usr/local/freeswitch/
FreeSwitch所需的端口列表(需在防火墙设置里打开):http://wiki.freeswitch.org/wiki/Firewall
FreeSwitch默认只支持音频,为支持视频,修改vars.xml如下:
<X-PRE-PROCESS cmd="set" data="global\_codec\_prefs=PCMU,PCMA,GSM,**H264,H263-1998,H263**"/>
<X-PRE-PROCESS cmd="set" data="outbound\_codec\_prefs=PCMU,PCMA,GSM,**H264,H263-1998,H263**"/>
FreeSwitch安装后缺省用户是1000~1020,密码均为1234。用任意sip客户端(boghe, linphone, x-lite等等)登录,拨9664应该可以听到等待音乐,说明安装成功了。还有一些功能号码,总结如下:
\------------------
号码 | 说明
\----------------------
9664 | 保持音乐
9196 | echo,回音测试
9195 | echo,回音测试,延迟5秒
9197 | milliwatte extension,铃音生成
9198 | TGML 铃音生成示例
5000 | 示例IVR
4000 | 听取语音信箱
33xx | 电话会议,48K(其中xx可为00-99,下同)
32xx | 电话会议,32K
31xx | 电话会议,16K
30xx | 电话会议,8K
2000-2002 | 呼叫组
1000-1019 | 默认分机号
曾遇到过一个问题,接通9664后立刻被自动挂断,接上摄像头后问题消失。
复制internal.xml为internal2.xml,修改internal2.xml里第一行的name为internal2,再将sip-ip和rtp-ip改为与internal里不同的那个公网ip,重启freeswitch即可。(用sofia status命令应该可以看到新建的internal2生效)
要使用智能域名解析,将vars.xml里的domain改为域名即可。
在profile文件里修改nat-options-ping属性为true,大约每30秒FreeSwitch会发一个options包给客户端以保持连接。
http://wiki.freeswitch.org/wiki/Sofia.conf.xml#nat-options-ping
中文语音包下载和使用方法:https://groups.google.com/forum/#!topic/freeswitch-cn/gYXmAv7sGKU
本文操作系统为CentOS,所用Opensips版本为1.8.2。
Update2013/6/27: 版本1.9.1也已验证通过,下载地址为http://opensips.org/pub/opensips/latest/src/opensips-1.9.1_src.tar.gz
(若已有环境可跳过此步骤)
1、安装虚拟机,VMWare Server 2.0遇到问题无法显示console(Chrome里),换为Virtualbox 4.2后可正常使用;
2、在虚拟机里安装CentOS 6.3,选择standard server
类型安装。
对这种纯命令行界面的虚拟机,可以用telnet直接访问,操作剪贴板什么的比较方便;
若虚拟机映射的网卡没有自动启动,用ifup eth0
命令启动。
若(Virtualbox的)虚拟机是复制过来的,可能需要先删除 /etc/udev/rules.d/70-persistent-net.rules
,再修改/etc/sysconfig/network-scripts/ifcfg-eth0
里的HWAddr地址。
若需要配置网卡ip地址,先ifconfig -a
查看网卡设备号和MAC地址,然后编辑/etc/sysconfig/network-scripts/ifcfg-eth0
文件,示例如下:
DEVICE="eth0" BOOTPROTO\="none" HWADDR\="08:00:27:81:30:F4" NM\_CONTROLLED\="yes" ONBOOT\="yes" TYPE\="Ethernet" UUID\="dcd43c45-adf4-480b-b461-179ee8d2e8d6" IPADDR\=192.168.1.120 NETMASK\=255.255.255.0 GATEWAY\=192.168.1.1
在/etc/resolv.conf
里指定dns以便安装软件包(CentOS6以后可以在ifg-eth0里指定dns了)
nameserver 202.181.202.140 nameserver 208.67.220.220
opensips提供了一个视频教程(这个页面有下载链接,90M),推荐使用menuconfig方式,更方便且不容易出错。以下为步骤摘要:
yum install gcc make
yum install flex bison ncurses libncurses-dev ncurses-devel
yum install mysql mysql-server mysql-libs mysql-devel
wget http://opensips.org/pub/opensips/1.8.2/src/opensips-1.8.2\_src.tar.gz
tar zxvf opensips-1.8.2\_src.tar.gz
cd opensips-1.8.2-tls
make menuconfig (勾选db\_mysql,其他不用动)
菜单里选"Compile And Install Opensips"
退出menuconfig
vi /usr/etc/opensips/opensipsctlrc,把与mysql有关的注释去掉(DB\_PATH和USERCOL保留注释)
service mysqld start
opensipsdbctl create(提示的两个问题都选no)
osipsconfig (选择ENABLE\_TCP,USE\_AUTH,USE\_DBACC,USE\_DBUSERLOC,USE\_DIALOG,然后generate residential script)
用生成的opensips\_residential\_xxx.cfg替换原先的opensips.cfg
vi /usr/etc/opensips/opensips.cfg (改listen地址和mpath,后者一般是/usr/lib/opensips/modules)
opensipsctl start (netstat -anp查端口)
service iptables stop (关闭防火墙)
如果启动opensips时提示错误,检查/var/log/messages
(若opensips.cfg里设置了log_stderror=no则日志都进入此文件,链接),一般是模块参数未设置引起的。例如在log里发现:
“ERROR:uri:db\_checks\_fixup1: configuration error - no database URL is configured!”
则在opensips.cfg
里的loadmodule "uri.so"
后添加modparam("uri", "db\_url","mysql://opensips:opensipsrw@localhost/opensips")
即可。
创建测试用户:
opensipsctl add 101 101
如果创建用户时提示ERROR: domain unknown: use usernames with domain or set default domain in SIP\_DOMAIN
,可修改opensipsctlrc
文件将SIP\_DOMAIN
设为本机域名或IP地址。
设置日志输出方式
在opensips.cfg
里有几个参数控制日志的输出:
debug=3 #此值控制日志输出的详细程度,3为普通,4为详细(会产生很多日志)。
log\_stderror=no #设置为no表示将日志输出到文件,否则输出到控制台(应该是以前台方式启动opensips服务时才有用)。
log\_facility=LOG\_LOCAL0 #应该是用于在syslog服务的配置文件里区分opensips产生的日志(见下面“使用独立的log文件”)。
fork=yes #设置为yes表示在后台启动opensips服务,设置为no表示在前台启动。
使用独立的log文件
opensips使用syslog服务,所以缺省情况下日志会进入/var/log/message
这个文件,如果希望使用独立的log文件,可以这样设置:
touch /var/log/opensips.log
vi /etc/rsyslog.conf --> 增加一行:local0.\* /var/log/opensips.log
/etc/init.d/rsyslog restart
配置STUN模块
opensips自带一个stun模块,可以实现stun服务器的功能(需要双网卡)。配置方法也很简单(官方文档),在opensips.cfg里添加如下内容:
\#### STUN module
loadmodule "stun.so"
modparam("stun", "primary\_ip", "11.22.33.44") #opensips服务器的ip地址
modparam("stun", "primary\_port", "5060") #必须与opensips的udp端口相同(一般是5060)
modparam("stun", "alternate\_ip", "55.66.77.88") #另一网卡的ip地址
modparam("stun", "alternate\_port", "3479") #另一端口号
配置好stun以后,可以使用stun-client来测试,以windows下为例,测试命令为:
stun-client-0-96.exe 11.22.33.44:5060 -v
安装配置RTPProxy模块
rtpproxy模块通常与nathelper模块一起使用。首先要确保服务器上已经安装了rtpproxy,启动rtpproxy:
rtpproxy -F
然后在opensips.cfg
文件里做如下配置:
loadmodule "rtpproxy.so"
modparam("rtpproxy", "rtpproxy\_sock", "unix:/var/run/rtpproxy.sock") # CUSTOMIZE ME
安装配置MediaProxy模块
MediaProxy官方文档链接
一个在CentOS6上安装MediaProxy2.5.2的参考链接。
下载mediaproxy源码(和所需要的各种依赖包),并安装(过程略)。安装完成后:
把config.ini.sample
复制到/etc/mediaproxy/config.ini
,把tls目录也复制过来。
echo 1 > /proc/sys/net/ipv4/ip\_forward
media-dispatcher restart
media-relay restart
在opensips.cfg
里配置mediaproxy模块,如下:
\#### MediaProxy module
loadmodule "mediaproxy.so"
modparam("mediaproxy", "disable", 0)
#modparam("mediaproxy", "mediaproxy\_socket", "/var/run/mediaproxy/dispatcher.sock")
modparam("mediaproxy", "mediaproxy\_timeout", 500)
modparam("mediaproxy", "signaling\_ip\_avp", "$avp(nat\_ip)")
modparam("mediaproxy", "media\_relay\_avp", "$avp(media\_relay)")
若mediaproxy提示No suitable relay found
,可能是certification方面的问题。 参考链接
(未完)
抓取SIP包
在Opensips所在服务器上使用tcpdump可以抓取SIP包以便分析问题(注意要抓取的网卡是eth0或eth1):
tcpdump -nqt -s 0 -A -i eth0 port 5060 -w /home/capture\_file\_name.pcap
参考:http://jonathanmanning.com/2009/10/26/how-to-voip-sip-capture-with-tcpdump-on-linux/
要抓手机上的包稍微复杂一些,要先root手机,然后把tcpdump复制到手机上使用:
adb shell
su
tcpdump -nqt -s 0 -w /sdcard/packets\_xx.pcap
adb pull /sdcard/packets\_xx.pcap
具体请参考这篇文章。
从sourceforge下载opensips-cp源码压缩包后,里面附有名为INSTALL的文档,建议根据这个文档进行安装,网上能查到的一些资料往往是过期的或不准确的。
yum install httpd php php-mysql php-xmlrpc php-pear
pear install MDB2
pear install MDB2#mysql
pear install MDB2#mysqli
pear install log
在/etc/php.ini
里:
把short\_open\_tag
置为On
把/usr/share/pear
加到inculde\_path
变量里(一些教程写的是加/usr/share/php,实际检验要加/usr/share/pear)
wget http://sourceforge.net/projects/opensips-cp/files/opensips-cp/5.0/opensips-cp\_5.0.tgz/download
tar -zxvf opensips-cp\_5.0.tgz
将解压缩后的文件夹(名字一般是“5.0”)复制到/var/www
目录下,并改名为opensips-cp
vi /etc/httpd/conf/httpd.conf,添加下面一行:
Alias /cp "/var/www/opensips-cp/web"
chown apache:apache /var/www/opensips-cp/config/access.log (如果是其他版本linux,用户名可能是www-data或其他)
(随源码附带的安装文档INSTALL有点看不懂,postgresql应该是与mysql二选一。)
安装必须的admin:
cd /var/www/opensips-cp/config/tools/admin/add\_admin/
mysql -Dopensips -p<ocp\_admin\_privileges.mysql
mysql -uroot opensips进入mysql命令行,执行下面的命令添加管理员用户:
INSERT INTO ocp\_admin\_privileges (username,password,ha1,available\_tools,permissions) values ('admin','admin',md5('admin:admin'),'all','all');
安装cdrviewer:
cd /var/www/opensips-cp/config/tools/system/cdrviewer/
mysql -Dopensips -p < cdrs.mysql
mysql -Dopensips -p<opensips\_cdrs.mysql
cd /var/www/opensips-cp/cron\_job
vi generate-cdrs\_mysql.sh (填写数据库连接信息)
注意,generate-cdrs\_mysql.sh
这个文件里的call opensips\_cdrs\_1\_6()
可能要改为call opensips\_cdrs()
,必须要与opensips\_cdrs.mysql
里定义的名称一致。
vi /etc/crontab
添加定时任务,例如每三分钟生成一次:
\*/3 \* \* \* \* root /var/www/opensips-cp/cron\_job/generate-cdrs\_mysql.sh
安装smonitor:
(此处INSTALL文档有笔误,这里已更正)
cd /var/www/opensips-cp/config/tools/system/smonitor/
mysql -Dopensips -p < tables.mysql
vi /etc/crontab
添加定时任务,例如每分钟一次:
\* \* \* \* \* root php /var/www/opensips-cp/cron\_job/get\_opensips\_stats.php > /dev/null
安装add_user:
(最前面已经装过了ocp\_admin\_privileges.mysql
,这里应该不需要再做一次,INSTALL文档的小问题不少)
启动opensips-cp:
service mysqld start
service httpd start
打开浏览器访问http://xxx.xxx.xxx.xxx/cp/ 应该能看到登录界面,用之前创建的admin用户登录。
Best practices for SIP NAT traversal
服务器端保持连接:使用 nat_traversal或nathelper模块(根据讨论组里的一些帖子,这两个模块的功能几乎相同),让opensips每个一段时间向客户端发一个包,使得路由器上的端口映射将保持(即洞口一直打开)。在客户端抓包时应该可以看到这些来自服务器的sip包,一般名称为OPTIONS。
客户端接收到INVITE命令后没有RING:很奇怪的问题,但在我这里时不时的发生,客户端程序为Boghe v2.0.153.836,暂时还没有找到原因和解决方法。
路由器修改SIP包:使用Volans VE602W作为路由器,从客户端发出的REGISTER包里的Via字段会被修改为公网地址,导致opensips服务器判断是否来自内网(nat_traversal模块中的nat_client_test方法)失败,其他三个路由器(TPLink、Mercury和Buffalo没有这种情况)。暂时没有找到解决方法。这里有一个类似问题。
客户端接收到重复的OPTIONS消息:由于重复(通过不同路由器)登录到opensips,Opensips有时会发送多个OPTIONS包给客户端,直到服务器认为客户端已经掉线。若客户端在REGISTER消息的Contact字段里添加了expires=xxx时,服务器会在location表里记录客户端失效的时间,若这个时间很长则服务器会一直尝试连接客户端。
有时接通以后没有视频画面:遇到过这样的问题:拨打十次,每次都能接通,但有时没有画面。后来发现是服务器防火墙禁止了一些端口(用iptables --list INPUT查询发现服务器仅允许udp 35000~50000进入)。解决方法是启动rtpproxy时指定端口范围,例如rtpproxy -m 40000 -M 50000 -F。
Contact URI字段没有被改为公网IP:通过增加调试信息发现虽然fix_nated_contact()方法已经被调用,但服务器端发回的sip包里Contact URI里的内网地址并没有被替换为公网地址。在公司没有这个问题,在家有这个问题(更换路由器无效),暂时没找到原因。(更正:这个问题本身有误,应该观察从服务器返回的200OK消息,而不是服务器接收到的原始消息)
单向有声音/视频或仅音频能拨通:可能是SIP包的长度超出了网络设备的MTU值,在UDP协议下,如果客户端不能处理过长的SIP包(一般是带有SDP的那些SIP消息,而且视频请求比音频请求产生的SIP消息要大),多出的部分可能会被丢弃,导致服务器发送/接收的SIP包失效。解决办法有:1)切换到TCP协议;2)精简SIP包尺寸,有些客户端生成的SIP包里带有不必要的字段可以删除掉(如果能够定制开发的话),另外这里有一个参考链接;3)使用支持超长UDP包或SIP包比较小的客户端(我用的基于doubango的boghe这部分做的不太好,换用x-lite后发现同样的请求SIP包长度小很多:18xx vs 10xx)。
清除在线用户:用opensipsctl ul rm id
可以删除一个在线用户,一个用户段时间内多次登录时会造成重复记录,这时可能需要清除掉这个用户的在线状态。
(本文原文链接:https://www.cnblogs.com/bjzhanghao/archive/2013/02/13/2910903.html)
我的笔记本Win7系统连了一个无线鼠标,电脑待机后若不小心碰到鼠标就会被唤醒。
网上有一些文章说在“鼠标硬件->电源选项”里清除“允许鼠标唤醒电脑”选项,但在我这里完全不起作用。
看到其他人也有类似的问题(例如这个链接里),但没有发现进一步的解决方法。自己乱试了一通,最后当我清除掉“键盘”的“允许唤醒电脑”选项后,鼠标居然可以不唤醒电脑了——晕,但是目的达到了。
我用的是罗技的M215无线鼠标,猜测Windows7系统把鼠标的无线接收器当作键盘设备了。
有同样问题的不妨试试。