2016年12月27日星期二

2016年12月18日星期日

Intellij中spring jpa entity "cannot resolve symbol"

see this link: http://stackoverflow.com/questions/12420996/intellij-idea-highlights-entity-class-names-with-cannot-resolve-symbol-in-jp

选择project structure中的facet,新建JPA,新增一个JPA Provider的persistence.xml,打开intellij左侧的persistence,右键选择new -> Persistence Unit,done。

2016年12月12日星期一

spring boot注入静态变量

private static String test;

@Value("${test}")
public void setXxx(String test) {
  Test.test = test;
}

遇到一个问题,如果这个static变量是要传给Test类的super方法调用:
public Test() {
  super(test);
}
执行顺序是先调用构造方法,后调用set方法,不能满足需求。

解决方法1:
public Test(@Value("${test}") String test) {
  super(test);
}

解决方法2:
把super父类中的用到test变量逻辑抽成了protected方法loadTest(test),在子类中调用,不再通过super传参调用:
public Test() {
  super();
}

@PostConstruct
public void init() {
  loadTest(test);
}

spring boot使用@PostConstruct初始化static变量

在类中定义private static变量,然后使用@PostConstruct:
@PostConstruct
public void init() {
}
init()中给static变量赋值

spring boot @Value注解值为空

对spring不熟的原因,使用@Value怎么改都是null。
原因是我在自己的类中(service层用到)使用了@Value,这并不起作用,然后我在类前面加了@Component注解,依然是null。
最后,我在service层@Autowired自动注入了该类,而不是自己new,问题解决了,折腾挺久...
总结一下,如果用Spring注解,不能自己new一个类。

spring boot启动问题

使用了@Configuration注解,启动时候报错:
Caused by: java.lang.IllegalArgumentException: No visible constructors in class ...

发现是我这个类的构造函数设为了private,改为protected后解决...

2016年12月3日星期六

spring boot中log4j打不出日志的问题

打开pom.xml的Dependency Analyzer,查看All Dependencies as Tree,搜索log4j,发现spring-boot-starter-web中引入了log4j-over-slf4j的依赖,并不是我们用的log4j,右键选择exclude将log4j-over-slf4j去掉,然后重新在pom.xml中添加log4j的依赖,问题解决。

2016年11月11日星期五

gitlab配置完成后502错误解决方法

参考http://www.yuzhewo.com/2015/11/03/%E4%BF%AE%E6%94%B9gitlab%E4%BD%BF%E7%94%A8%E7%8E%B0%E6%9C%89nginx%E6%9C%8D%E5%8A%A1%E5%8F%8A502%E9%97%AE%E9%A2%98%E8%A7%A3%E5%86%B3/

我用的不是gitlab自带的nginx。

查看日志:
tailf /var/opt/gitlab/nginx/logs/gitlab_error.log
发现是unix:/var/opt/gitlab/gitlab-workhorse/socket failed (13: Permission denied),因为nginx没有socket文件的权限。

ll /var/opt/gitlab/gitlab-workhorse/socket,查看socket所在的用户组是git。

chgrp gitlab-www /var/opt/gitlab/gitlab-workhorse/socket修改socket的用户组为gitlab-www。

在/etc/gitlab/gitlab.rb文件中增加以下配置:
web_server['external_users'] = ['nginx']

重新加载gitlab:gitlab-ctl reconfigure,问题解决。

后来遇到gitlab无法加载的问题,尝试了很多gitlab-ctl stop然后再start,gitlab-ctl reconfigure。
ps aux | grep sidekiq,杀掉了sidekiq的进程,然后gitlab-ctl start,居然解决了。前面修改的socket所属用户组又变回git了,这个问题待解决。

第一次访问会要求重设root密码。为了安全我们在管理页面可以新建一个普通用户,注意新建用户过程中不能设置密码,在建立成功之后可以edit这个账号然后这里可以设置密码。

关闭注册功能:
默认注册功能是开启的,需要考虑关闭注册功能。
用管理员账号登录之后, 进入”Admin area”, 点”settings”, 取消”Signup enabled”。

linux用户和用户组命令

usermod:http://urchin.blog.51cto.com/4356076/987186

把某用户加入到某个组中:
gpasswd -a username groupname

把组中的某个用户删除:
gpasswd -d username groupname

修改文件所属用户:
chown 用户 目录或文件名

修改文件所在用户组:
chgrp 组 目录或文件名

2016年11月10日星期四

2016年11月9日星期三

2016年11月3日星期四

eclipse中导入java web项目问题汇总

1、import javax.servlet.http错误

参考http://yl-fighting.iteye.com/blog/1409468

在这之前需要已经有安装tomcat,下载解压好tomcat后参考http://www.cnblogs.com/marineoxy/p/5084382.html

2、查看markers发现Target runtime Apache Tomcat 7.0 is not defined

我配置的是tomcat 8.0,修改了项目文件夹中.settings/org.eclipse.wst.common.project.facet.core.xml

3、Build path specifies execution environment JavaSE-1.7. There are no JREs installed in the workspace that are strictly compatible with this environment.

参考http://stackoverflow.com/questions/3138384/warning-build-path-specifies-execution-environment-j2se-1-4

4、Implementation of project facet jst.web.jstl could not be found. Functionality will be limited.

由于MyEclipse里的用到了jstl,导入到Eclipse里也带过来了,修改.settings/org.eclipse.wst.common.project.facet.core.xml,删除jst.web.jstl这行

5、运行时Context initialization failed

[ERROR] - org.springframework.web.context.ContextLoader -ContextLoader.java(307) -Context initialization failed
  org.springframework.beans.factory.BeanDefinitionStoreException: Failed to read candidate component class: file [/Users/chenxiaoyu/Documents/Toolkit/apache-tomcat-8.0.38/webapps/meathub_data/WEB-INF/classes/com/zhaorou/action/ProductController.class]; nested exception is java.lang.IllegalArgumentException

我导入的项目是用spring 3,但我用的是java 1.8,版本不兼容,要么升级为spring 4,要么降级为java 1.7

2016年10月26日星期三

maven 为测试环境、生产环境等不同环境打包

参考http://www.blogjava.net/fancydeepin/archive/2015/06/27/maven-p.html

在pom中添加:
<profiles>
  <profile> <!-- 可以通过 -P ID 来激活 -->
    <id>PROD</id> <!-- ID 标识符 -->
    <properties>
      <env>PROD</env> <!-- properties 定义 key-value, 这里 key 是 env, value 是 PROD -->
    </properties>
    <activation>
      <activeByDefault>true</activeByDefault> <!-- 默认激活 -->
    </activation>
  </profile>
  <profile> <!-- 可以通过 -P ID 来激活 -->
    <id>TEST</id> <!-- ID 标识符 -->
    <properties>
      <env>TEST</env> <!-- properties 定义 key-value, 这里 key 是 env, value 是 TEST -->
    </properties>
  </profile>
</profiles>

编译时使用mvn install -P ID即可。

2016年10月17日星期一

pom中引入本地jar包

将jar包放入工程目录下,增加dependency:
    <dependency>
      <groupId>xxx.xxx.xxx</groupId>
      <artifactId>xxx</artifactId>
      <version>1.0</version>
      <scope>system</scope>
      <systemPath>${project.basedir}/xxx.jar</systemPath>
    </dependency>

2016年10月13日星期四

2016年10月11日星期二

pycurl使用中的一个问题

curl了很多次url请求,总是随机的出现Pycurl and io.StringIO - pycurl.error: (23, 'Failed writing body)的错误,参考 http://stackoverflow.com/questions/19606447/pycurl-and-io-stringio-pycurl-error-23-failed-writing-body 解决了问题。

2016年10月9日星期日

中文分词

常用方法有:
1. 基于词典的分词方法(机械分词法)
  最大正向匹配法(Forward Maximum Matching, FMM)
  逆向最大匹配法(Reverser Maximum Matching, RMM)
  最少切分法(使每一句中切出的词数最小)
  双向匹配法(Bi-directional Maximum Matching, BMM)
  全切分(http://yangshangchuan.iteye.com/blog/2209761) 效率低,应用不多
2. 基于统计的分词方法
  HMM
  CRF
3. 基于深度学习的方法

参考:
http://www.dianacody.com/2014/11/05/cn_cutwords.html
http://www.open-open.com/lib/view/open1420814197171.html
http://h2ex.com/1282

word2vec overview

https://blog.acolyer.org/2016/04/21/the-amazing-power-of-word-vectors/

http://blog.csdn.net/itplus/article/details/37969519系列

python中包含utf-8中文的列表或字典输出

直接print会出现以下结果:
>>> print list
['\xe6\x88\x91\xe8', '\xe7\x8b\x97']

使用json.dumps可以输出中文:
import json
print json.dumps(list, encoding="UTF-8", ensure_ascii = False)

使用','.join(list)也可以正确输出中文。

2016年10月5日星期三

解决手机无法连接Charles代理的问题

Mac中使用Charles抓包,手机设置了http代理,Charles设置也没错,但手机一直连不上网。

排查原因:
电脑和手机之间是否能ping通,发现电脑能ping通手机,手机无法ping通电脑。

解决:
系统防火墙已经关了,后来发现是我装了McAfee杀毒软件的防火墙的问题,关闭防火墙后问题解决。系统防火墙开启也不影响。

如果电脑和手机互相ping不通并且防火墙已经关闭,可能是路由器设置问题。

2016年9月22日星期四

解决Pig中ERROR 1071: Cannot convert a map to a String

运行Pig脚本时遇到这样的问题:
ERROR 1071: Cannot convert a map to a String

后来发现原因是map的一个字段值为空字符串,我在后面取了这个字段的值:(chararray)$0#'field' AS field,然后就出错了。所以我在这之前将filed字段为''的都FILTER BY $0#'field' != ''之后问题解决。

2016年9月14日星期三

Spark中解析json

建议使用fastjson:
libraryDependencies += "com.alibaba" % "fastjson" % "1.2.24"


其他一些方案(不推荐):

scala.util.parsing.json.JSON:
解析:JSON.parseFull(x).get.asInstanceOf[Map[String, Any]]
生成:JSONObject(Map("field" -> value, ...))

或者com.fasterxml.jackson解析和生成json。

2016年9月13日星期二

Spark join的用法

用一个例子说明一下:
val a = sc.parallelize(List((1, "a"), (3, "c"), (5, "e"), (6, "f")))
val b = sc.parallelize(List((1, "a"), (2, "b"), (3, "c"), (4, "d")))

a.join(b).collect
    Array[(Int, (String, String))] = Array((1,(a,a)), (3,(c,c)))

a.leftOuterJoin(b).collect
    Array[(Int, (String, Option[String]))] = Array((1,(a,Some(a))), (6,(f,None)), (3,(c,Some(c))), (5,(e,None)))

a.rightOuterJoin(b).collect
    Array[(Int, (Option[String], String))] = Array((4,(None,d)), (1,(Some(a),a)), (3,(Some(c),c)), (2,(None,b)))

a.fullOuterJoin(b).collect
    Array[(Int, (Option[String], Option[String]))] = Array((4,(None,Some(d))), (1,(Some(a),Some(a))), (6,(Some(f),None)), (3,(Some(c),Some(c))), (5,(Some(e),None)), (2,(None,Some(b))))

a.subtractByKey(b).collect
    Array[(Int, String)] = Array((5,e), (6,f))

如果a或者b中有重复的key,join的结果会有多条。

2016年9月12日星期一

解决scala.reflect.api.JavaUniverse.runtimeMirror(Ljava/lang/ClassLoader;)Lscala/reflect/api/JavaMirrors$JavaMirror的问题

运行Spark的时候遇到这样一个问题:
java.lang.NoSuchMethodError: scala.reflect.api.JavaUniverse.runtimeMirror(Ljava/lang/ClassLoader;)Lscala/reflect/api/JavaMirrors$JavaMirror;

首先检查了一下我打包时候的Spark版本是基于scala 2.11的Spark 2.0.0,和spark-submit的版本是一致的,问题还是没有解决。最后发现是我的pom.xml中maven-scala-plugin的jvm版本设置的不对,修改了正确的jvm版本后运行成功。

2016年9月8日星期四

spark中dbscan使用中遇到的问题

Spark中目前没有集成dbscan聚类算法,见https://issues.apache.org/jira/browse/SPARK-5226

找了三个项目:
1、https://github.com/scalanlp/nak
nak中dbscan的输入必须是一个breeze.linalg.DenseMatrix的矩阵包含了所有数据,并不是我所需要的RDD[Vector],不可用。

2、https://github.com/irvingc/dbscan-on-spark
输入是一个RDD[Vector],但代码中只考虑了Vector的前两个值,所以该项目只能计算二维的dbscan,需要自己修改代码支持多维的Vector。

因为我用的Spark 2.0.0,而这个项目用的1.6.1,org.apache.spark.Logging类不存在了,我改为了org.apache.spark.internal.Logging。

运行时又遇到另外一个bug:
java.lang.NoSuchMethodError: scala.collection.immutable.$colon$colon.hd$1()Ljava/lang/Object;
看了一下代码,不知道为什么运行时不支持EvenSplitPartitioner.scala文件中的case (rectangle, count) :: rest => 这种List的写法,所以我将这段改为了获取List的head和tail,重新编译,提交spark运行,终于成功。

另外,该项目的repo中没有最新版本的jar,所以只能通过源码进行打包。

3、https://github.com/alitouka/spark_dbscan
目前只支持csv格式的文件作为输入,每行用逗号隔开。
同样,该项目是基于Spark 1.1.0写的,修改为2.0.0时要删去Logging类。

看了一下代码,如果不用IOHelper.readDataset方法,可以直接将数据转为RDD[Point]后进行计算。

运行了一下,发现vector维度为10000时候小数据量就报错,维度1000时大数据量也会出错,该问题目前还没有解决。

2016年9月1日星期四

mallet中LDA的使用

mallet是一个机器学习的Java库,不支持分布式,总结一下其中的Topic Model的用法。

命令行使用中有两种import data的方式,一种是import-dir,一个文件是一个Instance,有多个文件;另一种是import-file,只有一个文件,每一行是一个Instance。
命令行的使用方法移步http://mallet.cs.umass.edu/topics.php

mallet中以instance为单位表示文档,每一个Instance包括name、label、data、source。mallet中使用不同的Iterator来载入document的文件。
csv文件格式的例子(CsvIterator):http://mallet.cs.umass.edu/topics-devel.php
文本文件的例子(FileIterator):http://mallet.cs.umass.edu/import-devel.php
所有的Iterator见cc.mallet.pipe.iterator。

InstanceList的addThruPipe方法既可以添加Iterator<Instance>也可以添加单独的一个Instance。

两种级别的正则表达式:
1、line regex
用于从每一行文本中提取name、label、data:
instances.addThruPipe(new CsvIterator (fileReader, Pattern.compile("^(\\S*)[\\s,]*(\\S*)[\\s,]*(.*)$"), 3, 2, 1)); // data, label, name fields
参考http://stackoverflow.com/questions/27927556/what-do-the-parameters-of-the-csviterator-mean-in-mallet/27929358#27929358

2、data regex
用于从data中提取出token:
new CharSequence2TokenSequence(Pattern.compile("\\p{L}[\\p{L}\\p{P}]+\\p{L}"))
参考http://mallet.cs.umass.edu/import.php中关于--token-regex的说明。

2016年7月30日星期六

解决mvn test没有运行Scala Test

http://stackoverflow.com/questions/13036561/trying-to-get-scalatest-working-there-are-no-tests-to-run-when-doing-mvn-tes

在pom的plugin中增加:
<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-surefire-plugin</artifactId>
  <version>2.7</version>
  <configuration>
    <skipTests>true</skipTests>
  </configuration>
</plugin>
<plugin>
  <groupId>org.scalatest</groupId>
  <artifactId>scalatest-maven-plugin</artifactId>
  <version>1.0</version>
  <configuration>
    <reportsDirectory>${project.build.directory}/surefire-reports</reportsDirectory>
    <junitxml>.</junitxml>
    <filereports>WDF TestSuite.txt</filereports>
  </configuration>
  <executions>
    <execution>
      <id>test</id>
      <goals>
        <goal>test</goal>
      </goals>
    </execution>
  </executions>
</plugin>
参考http://www.scalatest.org/user_guide/using_the_scalatest_maven_plugin

2016年7月29日星期五

Spark单元测试中使用mockito打桩

pom构建添加依赖:
    <dependency>
      <groupId>org.apache.spark</groupId>
      <artifactId>spark-core_2.10</artifactId>
      <version>${spark.version}</version>
      <type>test-jar</type>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>org.mockito</groupId>
      <artifactId>mockito-all</artifactId>
      <version>1.9.5</version>
    </dependency>

sbt构建添加依赖:
"org.apache.spark" %% "spark-core" % "2.0.0" % "test" classifier "tests",
"org.mockito" % "mockito-all" % "1.9.5" % "test"


对class中的方法打桩(不能对class中变量打桩),使用spy。一个例子:
ReadFile.scala:
import org.apache.spark.SparkContext
import org.apache.spark.rdd.RDD

class ReadFile(sc: SparkContext) extends Serializable{
  def input: RDD[String] = {
    sc.textFile("hdfs://ip_address/xxx/data.txt")
  }

  def output = input.collect()
}

ReadFileSuite.scala:
import org.apache.spark.LocalSparkContext.withSpark
import org.apache.spark.{LocalSparkContext, SparkContext, SparkFunSuite}
import org.mockito.Mockito.{spy, when}

class ReadFileSuite extends SparkFunSuite with LocalSparkContext {
  test("test1") {
    withSpark(new SparkContext("local", "test")) { sc =>
      val data = spy(new ReadFile(sc))
      val stub_file = sc.textFile(getClass.getResource("/data.txt").getFile)
      when(data.input).thenReturn(stub_file)
      assert(data.output.length === 3)
    }
  }
}

ReadFileSuite中文件是从test/resources中读取的,而不是ReadFile中从hdfs读的路径。

如果class没有构造参数,可以使用mock(classOf[yourClass])创建mock的class。

参考了http://qiuguo0205.iteye.com/blog/1443344http://qiuguo0205.iteye.com/blog/1456528

2016年7月18日星期一

2016年7月16日星期六

windows中自定义键位

将capslock键替换为ctrl:

参考http://hushicai.com/2016/01/07/win7-jiang-CapsLock-ying-she-wei-Ctrl.html

新建caps_lock_to_ctrl.reg文件,内容如下:
Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Keyboard Layout]
"Scancode Map"=hex:00,00,00,00,00,00,00,00,02,00,00,00,1D,00,3A,00,00,00,00,00

运行后重启,完成。

交换左win键和左alt键:

参考http://blog.sina.com.cn/s/blog_69a4fbd70100rj59.html

"Scancode Map"=hex:00,00,00,00,00,00,00,00,02,00,00,00,5B,E0,38,00,38,00,5B,E0

将capslock键替换为左ctrl,同时交换win键和左alt键:
"Scancode Map"=hex:00,00,00,00,00,00,00,00,03,00,00,00,1D,00,3A,00,5B,E0,38,00,38,00,5B,E0

如何设置Scancode Map的值,参考:http://blog.chinaunix.net/uid-174325-id-3912617.html

2016年7月5日星期二

jetty调试和部署web项目

本地调试:
<plugin>
  <groupId>org.eclipse.jetty</groupId>
  <artifactId>jetty-maven-plugin</artifactId>
  <version>9.3.10.v20160621</version>
  <configuration>
    <httpConnector>
      <port>8081</port>
    </httpConnector>
    <stopPort>9966</stopPort>
    <stopKey>foo</stopKey>
  </configuration>
</plugin>

配置参考:https://www.eclipse.org/jetty/documentation/9.3.x/jetty-maven-plugin.html#jetty-stop-goal
jetty插件版本:http://search.maven.org/#search%7Cgav%7C1%7Cg%3A%22org.eclipse.jetty%22%20AND%20a%3A%22jetty-maven-plugin%22

mvn jetty:run

部署:
java -jar start-server.jar xxx port  // xxx为war包名

2016年6月27日星期一

maven打包可执行文件

<plugin>
    <artifactId>maven-assembly-plugin</artifactId>
    <configuration>
        <descriptorRefs>
            <descriptorRef>jar-with-dependencies</descriptorRef>
        </descriptorRefs>
        <archive>
            <manifest>
                <mainClass>com.mobvoi.mqtt.Main</mainClass>
            </manifest>
        </archive>
    </configuration>
    <executions>
        <execution>
            <id>make-assembly</id>
            <phase>package</phase>
            <goals>
                <goal>single</goal>
            </goals>
        </execution>
    </executions>
</plugin>

maven编译时跳过test

参见http://wolfchina.iteye.com/blog/69277

mvn install -Dmaven.test.skip=true 或者-DskipTests

2016年6月16日星期四

JDK8下maven使用maven-javadoc-plugin插件报错

参考:http://blog.csdn.net/thc1987/article/details/51314777

解决办法:
添加-Xdoclint:none配置
完整配置如下:
<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-javadoc-plugin</artifactId>
    <version>2.9</version>
    <executions>
        <execution>
            <id>attach-javadocs</id>
            <goals>
                <goal>jar</goal>
            </goals>
            <configuration>
                <additionalparam>-Xdoclint:none</additionalparam>
            </configuration>
        </execution>
    </executions>
</plugin>

2016年5月24日星期二

hadoop报错Going to preempt 1 due to lack of space

原因是ResourceManager资源分配不够,修改yarn-site.xml中 yarn.scheduler.minimum-allocation-mb / yarn.scheduler.maximum-allocation-mb / yarn.scheduler.minimum-allocation-vcores / yarn.scheduler.maximum-allocation-vcores 配置不要太大。
Hadoop资源配置参考:http://dongxicheng.org/mapreduce-nextgen/hadoop-yarn-configurations-resourcemanager-nodemanager/

2016年5月11日星期三

Linux文件和文件夹默认权限

文件的默认权限:644
文件夹的默认权限:755

chmod 644 file_name
chmod 755 directory_name

2016年5月10日星期二

CentOS中samba可以看到文件夹但无法写入

参考http://serverfault.com/questions/410806/can-connect-to-samba-but-access-denied-to-homes

执行chcon -t samba_share_t <share_folder>,解决。

如果没有权限访问文件夹,一种可能的原因是samba用户不属于该文件夹所属的用户和组。

2016年5月4日星期三

HBase启动之后没有HRegionServer进程

看了一下日志,是因为master和slave的时间不同步引起的:
2016-05-01 23:18:33,193 ERROR [PriorityRpcServer.handler=14,queue=0,port=16000] master.MasterRpcServices: Region server slave1,16020,1462349077653 reported a fatal error:
ABORTING region server slave1,16020,1462349077653: Unhandled: org.apache.hadoop.hbase.ClockOutOfSyncException: Server slave1,16020,1462349077653 has been rejected; Reported
time is too far out of sync with master.  Time difference of 233170863ms > max allowed of 30000ms

修改时间和网络时间同步保证集群中所有机器的时间都一致即可解决问题。

Windows中设置Java的默认字符集为UTF-8

Java中有出现中文乱码的情况,使用System.out.println(System.getProperty("file.encoding"));查看了系统的文件编码为GBK,将该变量的值设为UTF-8便可以解决问题。

可以在运行程序的时候指定编码,用-Dfile.encoding=UTF-8参数即可。

或者根据Java官方文档http://docs.oracle.com/javase/6/docs/platform/jvmti/jvmti.html#tooloptions在系统环境变量中增加一个变量,变量名为: JAVA_TOOL_OPTIONS, 变量值为:-Dfile.encoding=UTF-8,保存,重新打开ide运行,问题解决。

2016年4月19日星期二

Mac中安装pip等

sudo eash_install pip

安装virtualenv:
sudo easy_install virtualenv
创建虚拟环境:
virtualenv venv
source venv/bin/activate
退回全局python解释器:deactivate

安装flask:
sudo pip install flask

Mac下安装php-cgi

参考:https://gist.github.com/xiangshouding/9359739

$ brew install php55 --with-cgi
如果安装提示没有php55,请用 brew tap homebrew/homebrew-php 后再安装

或者:
mac一般自带php,但由于默认编译不带cgi,所以这部分安装可能会很麻烦。
采用的偷懒的办法,下载 http://fouber.github.io/install-php-cgi/ 中的php-mac版本,解压缩后,将bin/php-cgi直接复制到/usr/bin/下即可完成相应的使用。新版本的mac强化了安全机制,这种方法不建议使用。

IntelliJ IDEA中PHP配置参考:http://www.ifun.cc/blog/2014/02/09/macxia-pei-zhi-shen-qi-phpstromkai-fa-huan-jing/

2016年4月15日星期五

解决vi/vim中粘贴会在行首多很多缩进和空格的问题

参考:http://www.cnblogs.com/end/archive/2012/06/01/2531142.html

secureCRT会将你原来的文本原封不动的按照字符串的样式发送给服务器。所以当你的服务器上的vim设置为autoindent的话,在i模式下,那么它会将secureCRT传输而来的这些字符串再进行一下缩进。若你拷贝的文本中已经有表示缩进的空格或者制表符的话,它们也会被当成字符串,而被缩进。
解决办法:
1. 在拷贝前输入:set paste (这样的话,vim就不会启动自动缩进,而只是纯拷贝粘贴)
2. 拷贝完成之后,输入:set nopaste (关闭paste)

2016年4月14日星期四

Ubuntu安装gcc-4.8和g++-4.8

apt-get update时出了这个问题:
W: Failed to fetch gzip:/var/lib/apt/lists/partial/us.archive.ubuntu.com_ubuntu_dists_precise-backports_multiverse_binary-i386_Packages  Hash Sum mismatch

解决方法:
rm /var/lib/apt/lists/partial/*
apt-get clean
apt-get update

安装gcc-4.8和g++-4.8:
apt-get install python-software-properties
add-apt-repository ppa:ubuntu-toolchain-r/test
apt-get update
apt-get install gcc-4.8
apt-get install g++-4.8
update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-4.8 50
update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-4.8 50

2016年4月9日星期六

Linux常用命令和管道符的使用

显示以a字符为结尾的所有行:
cat filename | grep a$

显示长度小于10的所有行:
cat filename | awk 'length($0) < 10 {print $0}'

可以使用'| more'一页页查看cat的结果

统计出现"NA"的行数:
cat filename | awk 'match($0, "NA") > 0 {print $0}' | wc -l

head:
ls | head -n 1 只显示第一行

取第n行:
cat xxx | head -n | tail -1

sort:
-n 按数字大小排序
-r 倒序
-k 2 按照第二列排序
-u 去重
-k 1,1 去重时从第一个开始,第1个结束
-t , 逗号为分隔符
-g 支持科学计数法排序

保留行号排序:cat result | awk '{print $0 " " NR}' | sort -k 1 -n > sorted_result

uniq:
去重。-c统计个数

sed /xx/d 删除包含xx的所有行
  用\[来表示左方括号,]表示右方括号
sed '/xx/!d' 删除不包含xxx的所有行

awk -F ',' 以逗号分隔
awk '{$1="";print $0}' file 删除第一列
关于sed、awk的使用实例,参考link.

按列求和,假设文件只有一列:
cat filename | awk '{sum+=$1} END {print sum}'

将hdfs中某个文件夹中所有文件(包含子文件夹)拷贝到另外一个文件夹目录(只拷贝所有文件,不拷贝文件目录):
hadoop fs -ls -R $origin_path | awk '$5!=0 {print $8}' | xargs -I {} hadoop fs -cp {} $destination_path
将文件重命名为1、2、3...:
hadoop fs -ls -R $origin_path | awk '$5!=0 {print $8}' | awk '{print "hadoop fs -cp " $1 " " "$destination_path" NR}' | sh

倒序输出
cat filename | tac

查看启动进程的文件
ll /proc/$pid/exe

将文件中所有字符转成大写
tr "[:lower:]" "[:upper:]" < 1.txt > 2.txt

2016年4月6日星期三

MySQL解析JSON数据

参考:https://segmentfault.com/a/1190000003941100

1、数据量不大的情况下可以直接使用linux中管道符提取出对应的字段存为另一个文件,然后load进mysql中。
数据格式如下:{"category":"热销菜品","name":"盐酥菇"}
我只要取name字段:
cat dish_name.info | sed 's/.*"name":"\(.*\)".*/\1\tnot_found/g' > dish_name.temp

2、使用common-schema
下载了common_schema-2.2.sql之后,有两种方法安装:
Within MySQL, issue:
mysql> SOURCE '/path/to/common_schema.sql';

From shell, execute:
bash$ mysql < /path/to/common_schema.sql

mysql --local-infile -u root -p 进入mysql:

mysql> create table temp(a varchar(255));
mysql> load data local infile '/home/dish_name_info' into table temp;
mysql> select common_schema.extract_json_value(temp.a, '/name') from temp;

可以使用该方法取到name中的结果,然后将结果写进新的表中。

2016年4月5日星期二

Hive中使用first_value和max等窗口函数

遇到一个需求,统计不同的phone_device_id最近的event_timestamp的status值出现的次数,原始数据距离(phone_device_id, status, event_timestamp):
a 0 10
a 1 20
b 1 10
c 1 20
b 0 30
c 0 10
需要的结果:
0 1
1 2
因为a最新的状态是1,b最新的状态是0,c最新的状态是1,所以0总共有1个,1总共有2个。

可以使用以下语句实现,主要是max() over()和first_value() over():
select get_json_object(s2.first_value_window_1, '$.status'), count(distinct(phone_device_id)) from (select phone_device_id, max(event_timestamp) over (partition by phone_device_id), first_value(properties) over (partition by phone_device_id order by event_timestamp desc) from watch_upload_info where event_date = '2016-04-04' and get_json_object(properties, '$.action') = 'aw_status' and event = 'click') s2 group by get_json_object(s2.first_value_window_1, '$.status');

还可以使用另外一个方法:
先根据phone_device_id来分组取出event_timestamp最大的那条记录存到一张临时表中,然后和原表进行join得到status字段,然后再分组。

2016年3月25日星期五

Maven报错Missing artifact jdk.tools:jdk.tools:jar:1.8

参考:http://blog.csdn.net/u013281331/article/details/40824707
在pom.xml中加上依赖:
    <dependency>
      <groupId>jdk.tools</groupId>
      <artifactId>jdk.tools</artifactId>
      <version>1.8</version>
      <scope>system</scope>
      <systemPath>C:/Program Files/Java/jdk1.8.0_65/lib/tools.jar</systemPath>
    </dependency>
解决。

创建maven工程的一个问题

在eclipse中创建maven工程出现这样错误:
creating maven-archetype-quickstart has encountered a problem
unable to create project from archetype ...

尝试在命令行创建也遇到错误,这次的错误信息更多一些:
Unable to add module to the current project as it is not of packaging type 'pom' -> [Help 1]

原因:
创建工程的目录中存在了pom.xml文件,所以无法创建。

windows中解决eclipse中maven install时Unsupported major.minor version 51.0问题

maven install时报错:
Exception in thread "main" java.lang.UnsupportedClassVersionError: org/apache/maven/cli/MavenCli : Unsupported major.minor version 51.0

对应版本如下:
J2SE 8 = 52,
J2SE 7 = 51,
J2SE 6.0 = 50,
J2SE 5.0 = 49,
JDK 1.4 = 48,
JDK 1.3 = 47,
JDK 1.2 = 46,
JDK 1.1 = 45

maven install时要求jre版本必须在7以上,我没有导入自己安装的jre的路径,eclipse自带的是1.6版本的。
解决:在Windows -> Preferences中Java选项下的Installed JREs设置为JDK1.7以上的版本即可。

2016年3月24日星期四

解决python中使用protobuf,import xxx_pb2出错的问题

我在import xxx_pb2时遇到这样的问题:
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "VoiceSession_pb2.py", line 20, in <module>
    essionProtosP\x01'
TypeError: __init__() got an unexpected keyword argument 'syntax'

原因:protoc的版本和pip install protobuf的版本不统一。
运行protoc --version和pip list | grep protobuf分别查看两者的版本,保证版本统一错误即可解决。

Mac上item远程登录linux中文乱码问题

我使用的是zsh的终端,所以修改~/.zshrc,在最后加上:
export LC_ALL=en_US.UTF-8
export LANG=en_US.UTF-8

source ~/.zshrc,完成。

2016年3月21日星期一

ubuntu中配置不用每次都ssh-add输入passphrase

先安装expect:
apt-get install expect

我用的是root用户,/root/.ssh/xychen是你的key文件,chmod 600 /root/.ssh/xychen

vim /root/ssh-add.sh,内容如下:
#!/usr/bin/expect
spawn ssh-agent zsh
spawn ssh-add /root/.ssh/xychen
expect "Enter passphrase for /root/.ssh/xychen:"
send "your_passphrase\r"
interact

修改~/.bashrc文件,我使用的是zsh,所以修改~/.zshrc文件,在最后加上:
eval `ssh-agent`
/root/ssh-add.sh

putty中使用zsh无法显示绿色箭头

参考:http://blog.csdn.net/taoqick/article/details/40374425

需要更改putty字体,原来的字体设置无法显示箭头。

2016年3月13日星期日

tmux安装使用

MacOS中安装:
brew install tmux

Ubuntu中自带tmux

我的配置文件~/.tmux.conf:
set -g prefix C-a
unbind C-b
setw -g mode-keys vi
set -g automatic-rename off
set -g allow-rename off
set-option -g history-limit 65535
bind -n C-k clear-history
上面最后一行的配置是将clear-history命令绑定到ctrl+k快捷键,可以清除scrollback buffer。
配置文件参考:http://www.cnblogs.com/scue/p/3705309.html

配置完以后,重启tmux起效,或者先按C+b,然后输入:进入命令行模式, 在命令行模式下输入:
source-file ~/.tmux.conf

tmux中可以创建多个session,每个session可以创建多个窗口,每个窗口可以分割为多个窗格。
新建session:tmux new-session -s session_name
进入session:tmux a -t session_name
列出所有sessions:tmux list-sessions
关闭session:ctrl+d
删除所有session:tmux kill-server
删除指定session:tmux kill-session -t session_name
输出tmux剪贴板中的内容:tmux show-buffer

前缀键:我设置的是ctrl+a。快捷键:
系统操作:
? 显示帮助
d 脱离当前会话
[ 进入复制模式,按空格开始选中,回车结束选中,选中内容被复制
] 粘贴
: 进入命令模式

session操作:
$ 重命名session
s 以列表方式选择session
:new-session 新建session

窗口操作:
c 新建窗口
, 重命名窗口
w 以列表方式选择窗口
n 切换至下一个窗口
p 切换至上一个窗口
数字键 切换窗口
& 关闭窗口
l 切换到最后使用的窗口
} 与下一个窗格交换位
{ 与上一个窗格交换位置

窗格操作:
" 横向分割窗口
% 纵向分割窗口
q 选择窗格
; 切换至上一个窗格
o 切换至下一个窗格
z 全屏切换
方向键 切换窗格
alt+方向键 修改窗格大小
space 重新布局窗格
ctrl+a+o 交换窗格位置
x 关闭窗格

vim中y复制同步到tmux的缓冲区:
brew install reattach-to-user-namespace
同时添加配置如下:
# getting tmux to copy a buffer to system clipboard
set-option -g default-command "reattach-to-user-namespace -l zsh" # or bash...
bind y run "tmux save-buffer - | reattach-to-user-namespace pbcopy" \; display-message "Copied tmux buffer to system clipboard"
bind C-v run "reattach-to-user-namespace pbpaste | tmux load-buffer - && tmux paste-buffer"
http://foocoder.com/2013/07/28/zhong-duan-huan-jing-zhi-tmux/


更多参考:
https://gist.github.com/ryerh/14b7c24dfd623ef8edc7
http://mingxinglai.com/cn/2012/09/tmux/

tmux会source ~/.profile两次,奇怪的问题。

2016年3月12日星期六

zsh安装

参考http://yijiebuyi.com/blog/b9b5e1ebb719f22475c38c4819ab8151.html

Linux中安装:
apt-get install zsh git wget
wget https://github.com/robbyrussell/oh-my-zsh/raw/master/tools/install.sh -O - | sh
chsh -s /bin/zsh

MacOS中安装:
wget https://github.com/robbyrussell/oh-my-zsh/raw/master/tools/install.sh -O - | sh
chsh -s /bin/zsh

2016年3月11日星期五

使用Homebrew在Mac中安装或卸载软件

在终端中输入以下命令安装Homebrew
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

可以使用homebrew快捷地安装软件,比如:
brew install tmux
brew install zsh

brew uninstall tmux
brew uninstall zsh

2016年3月9日星期三

Mac中解决Latex中Support package 'expl3' too old.问题

l3kernel和l3packages版本过低,解决方法:
sudo tlmgr update l3kernel
sudo tlmgr update l3packages

2016年2月17日星期三

Hive远程客户端配置

准备一台新的客户机,拷贝hive使用的hadoop及hadoop的配置,设置HADOOP_HOME。拷贝已配置好的hive文件夹到新的机器,设置HIVE_HOME,修改PATH增加hadoop和hive。确保$HIVE_HOME/conf/hive-site.xml配置中的hive.aux.jars.path的hive文件夹路径正确。
如果已经设置了HADOOP_HOME或者将hadoop添加到了PATH中,执行hive确依然说没有找到hadoop,不妨看一下$HIVE_HOME/conf/hive-env.sh中有没有已经设置了错误的HADOOP_HOME路径,删掉即可。

将hadoop目录下的jline改为高版本:
cp $HIVE_HOME/lib/jline-2.12.jar $HADOOP_HOME/share/hadoop/yarn/lib/
rm $HADOOP_HOME/share/hadoop/yarn/lib/jline-0.9.94.jar

执行hive,完成。

Hadoop远程客户端配置

拷贝集群中的hadoop文件夹到新的客户机(主要是etc/hadoop/目录下的配置文件),vim ~/.bashrc,增加环境变量:

export HADOOP_HOME=your_hadoop_path
export PATH=$PATH:$HADOOP_HOME/bin:$HADOOP_HOME/sbin
export HADOOP_CLASSPATH=$HADOOP_HOME/share/hadoop/common/lib/*:$HADOOP_HOME/share/hadoop/common/*:$HADOOP_HOME/share/hadoop/hdfs/*:$HADOOP_HOME/share/hadoop/hdfs/lib/*:$HADOOP_HOME/share/hadoop/httpfs/tomcat/lib/*:$HADOOP_HOME/share/hadoop/mapreduce/*:$HADOOP_HOME/share/hadoop/mapreduce/lib/*:$HADOOP_HOME/share/hadoop/tools/lib/*:$HADOOP_HOME/share/hadoop/yarn/*:$HADOOP_HOME/share/hadoop/yarn/lib/*

source~/.bashrc,完成。

如果发现还是找不到class(已经设置了HADOOP_CLASSPATH,但是执行hadoop class命令时候发现classpath设置并没有生效),直接将HADOOP_CLASSPATH写入到hadoop和hdfs的脚本中去。问题原因不明。

将HDFS中JSON格式日志以日期分区导入Hive

下面看一个实例,按天进行分区。

数据格式如下,需要解析其中的部分字段:
{"version_name":"3.2.0","phone_system_fingerprint":"Xiaomi/libra/libra:5.1.1/LMY47V/V7.1.6.0.LXKCNCK:user/release-keys","phone_device_id":"ac614a689cdbb1ecd2713a4dbc008682","phone_device_type":"Mi-4c","watch_device_id":"7664e1b6eba4abc542ad5db0ce892fb7","properties":{"address":"中国,北京市,北京市,海淀区,海淀北二街,8号,39.989566,116.316318"},"type":"watch","version":"12600","deviceid":"ac614a689cdbb1ecd2713a4dbc008682","timestamp":"1455512510381","sys_version":"5.1.1","address":"中国,河北省,唐山市,路北区,和平路,,39.630073,118.136363","net_state":"","event":"user_connect","user_id":"ac614a689cdbb1ecd2713a4dbc008682","ticwear_version":"tic_3.2.1","watch_device_type":"Ticwatch","sys_model":"Mi-4c","channel":"main"}

1、首先用pig解析JSON,脚本如下:
REGISTER elephant-bird-pig.jar;
REGISTER elephant-bird-core.jar;
REGISTER elephant-bird-hadoop-compat.jar;
REGISTER json-simple.jar;

%default WATCH_UPLOAD_LOG /path/*.json

raw_log = LOAD '$WATCH_UPLOAD_LOG'
                USING com.twitter.elephantbird.pig.load.JsonLoader('-nestedLoad');

tic_log = FOREACH raw_log GENERATE
                 (chararray)$0#'version_name' AS version_name,
                 (chararray)$0#'phone_device_id' AS phone_device_id,
                 (chararray)$0#'watch_device_id' AS watch_device_id,
                 (chararray)$0#'phone_device_type' AS phone_device_type,
                 (chararray)$0#'properties'#'address' AS address,
                 (chararray)$0#'type' AS type,
                 (chararray)$0#'event' AS event,
                 (chararray)$0#'user_id' AS user_id,
                 (chararray)$0#'deviceid' AS device_id,
                 (chararray)$0#'ticwear_version' AS ticwear_version,
                 (chararray)$0#'watch_device_type' AS watch_device_type,
                 (chararray)$0#'sys_model' AS sys_model,
                 (chararray)$0#'timestamp' AS timestamp;

STORE tic_log INTO '/path/tic_log';

2、使用Hive导入数据:
create external table watch_upload_info_temp(version_name string, phone_device_id string, watch_device_id string, phone_device_type string, address string, type string, event string, user_id string, device_id string, ticwear_version string, watch_device_type string, sys_model string, `timestamp` bigint) row format delimited fields terminated by '\t' stored as textfile location '/path/tic_log';

create table watch_upload_info(version_name string, phone_device_id string, watch_device_id string, phone_device_type string, address string, type string, event string, user_id string, device_id string, ticwear_version string, watch_device_type string, sys_model string, `timestamp` bigint) partitioned by (time string);

set hive.exec.dynamic.partition.mode=nonstrict;
set hive.exec.max.dynamic.partitions = 10000;
set hive.exec.max.dynamic.partitions.pernode = 1000;

insert into table watch_upload_info partition(time) select *, from_unixtime(floor(`timestamp`/1000), "yyyy-MM-dd") time from watch_upload_info_temp where `timestamp` > 1417363200000;  -- 这里1417363200000是2014-12-01,timestamp是以ms为单位。

Pig

Please see this doc.

2016年2月16日星期二

Hive查看已存在的表是内部表或外部表

两种方法:
1) hive> desc formatted tbl_name
2) hive> desc extended tbl_name

Table Type是MANAGED_TABLE表示内部表,EXTERNAL_TABLE是外部表。

2016年2月15日星期一

pig中dump时无法连接server

pig默认的hdfs模式下dump数据到控制台出现以下提示信息:
org.apache.hadoop.ipc.Client - Retrying connect to server: host/ip:port.

解决:
Hadoop集群没有启动JobHistoryServer进程,执行命令:
mr-jobhistory-daemon.sh start historyserver

2016年2月2日星期二

reStructuredText语法

reST语法比较多,相比MarkDown还是有点复杂的,本文只记录了一部分。详情参考:链接

标题

for parts
#########

for chapters
*************

= for sections
- for subsections
^ for subsubsections
" for paragraphs
作为修饰的字符长度要大于等于文字长度

列表
# + - 都可以

无序列表:
# 列表1
    # 子列表
# 列表2

有序列表:
#. 列表1
#. 列表2

1. 列表1
2. 列表2

样式

**粗体**  *斜体*  ``引用``

保留原来的行样式:
| These lines are
| broken exactly like in
| the source file.

代码
::

    print(1)
    print(2)

下标
H\ :sub:`2`\ O

上标
E = mc\ :sup:`2`

表格

+------------------------+------------+----------+----------+
| Header row, column 1   | Header 2   | Header 3 | Header 4 |
| (header rows optional) |            |          |          |
+========================+============+==========+==========+
| body row 1, column 1   | column 2   | column 3 | column 4 |
+------------------------+------------+----------+----------+
| body row 2             | ...        | ...      |          |
+------------------------+------------+----------+----------+

=====  =====  =====
第1列  第2列  第3列
=====  =====  =====
8      1      6
3      5      7
4      9      2
=====  =====  =====

超链接
内嵌网址超链接:
`google <http://www.google.com.tw/>`_

可以把链接地址和目标定义分开:
google_

.. _google: http://www.google.com.tw/

注释
.. 注释

图片
.. image:: images/ball1.gif
    :height: 200
    :width: 300

2016年2月1日星期一

Spark中数据分区

Spark程序可以通过控制RDD分区来减少通信开销,所有的键值对RDD都可以进行分区。只有当数据集多次在比如join这种基于键的操作中使用时,分区才会有帮助。

一个例子:
有一张固定的用户信息表,以RDD(UserID, UserInfo)的形式保存在UserInfo中,另外有一个用户行为表,以RDD(UserID, LinkInfo)形式保存在LinkInfo中,现在统计在LinkInfo中但不在UserInfo中的topic个数。

不够高效的实现:
val userData = sc.sequenceFile[UserID, UserInfo]("hdfs://...").persist()

def processNewLogs(logFileName: String) {
  val events = sc.sequenceFile[User, LinkInfo](logFileName)
  val joined = userData.join(events)  // RDD of (UserID, (UserInfo, LinkInfo)) pairs.
  val offTopicVisits = joined.filter {
    case (userId, (userInfo, linkInfo)) => !userInfo.topics.contains(linkInfo.topic)
  }.count()
  println("Number of visits to non-subscribed topics: " + offTopicVisits)
}
以上代码中,连接操作需要将两个数据集中的所有键的哈希值都求出来,将该哈希值相同的记录传到同一台机器上,然后在那台机器上对所有键相同的记录进行连接操作。在每次调用时都对userData表进行哈希值计算和跨节点数据混洗,虽然userData的数据从来都不会变化。

使用数据分区实现:
val userData = sc.sequenceFile[UserID, UserInfo]("hdfs://..."
                         .partitionBy(new HashPartitioner(100)).persist()
在构建userData时候调用了partitionBy,Spark就知道了该RDD是根据键的哈希值来分区的,这样在调用join时,Spark就会利用到这一点。
当调用userData.join(events)时,Spark只会对events进行数据混洗操作,将events中特性UserID的记录发送到userData的对应分区所在的那台机器上。
注意,将分区之后的结果持久化是必要的,否则后面每次用到userData这个RDD时都会重新地对数据进行分区操作,partitionBy带来的好处就会被抵消,导致重复对数据进行分区以及跨节点的混洗。

可以从分区中获益的操作:
cogroup()、groupWith()、join()、leftOuterrJoin()、rightOuterJoin()、groupByKey()、reduceByKey()、combineByKey()、lookup()

对于RDD的pair,map()的结果不会有固定的分区,因为传给map()的函数理论上可以改变元素的键。不过Spark提供了mapValues()和flatMapValues(),可以保证每个二元组的键保持不变。

使用mapValues的PageRank的例子:
val links = sc.objectFile[(String, Seq[String])]("links").partitionBy(new HashPartitioner(100)).persist()
var ranks = links.mapValues(v => 1.0)  // 因为使用了mapValues,分区和links一样
for (i <- 0 until 10) {
  val contributions = links.join(ranks).flatMap {
    case (pageId, (links, rank)) =>
      links.map(dest => (dest, rank / links.size))
  }
  ranks = contributions.reduceByKey(_ + _).mapValues(v => 0.15 + 0.85 * v)
}
ranks.saveAsTextFile("ranks")

为了最大化分区相关优化的潜在作用,应该在无需改变元素的键时尽量使用mapValues()或flatMapValues()。

Spark中的累加器和广播变量

在使用map()或者filter()之类的函数时,可以使用在map外面定义的变量,但是无法改变变量的值。共享变量(累加器和广播变量)突破了这一个限制。

累加器
将文本按照空格分隔,顺便统计空行个数:
val file = sc.textFile("file.txt")
val blankLines = sc.accumulator(0)  // 创建Accumulator[Int]并初始化为0
val res = file.flatMap( line => {
    if (line == "") {
        blankLines += 1
    }
    lines.split(" ")
})

res.collect()  // 这里随便执行一个action,这样才会执行map中的运算
println(blankLines.value)

广播变量
在RDD的操作中如果每一次都使用同一个变量,驱动节点每次都会发送该变量到各个工作节点,如果变量很大,浪费了通信的开销,这种情况下可以使用广播变量,这个值只会被发送到各节点一次。
用法:
val broadcastVar = sc.broadcast(1)
sc.parallelize(1 to 10).map(_ + broadcastVar.value)

Spark的缓存

Spark在第一次调用动作并计算出RDD结果后,该动作的结果可以存储在集群的内存或者磁盘上,这样下一次需要调用依赖该RDD的动作时,就不需要从依赖关系中重新计算RDD,数据可以从缓存分区中直接返回。

例如,
cached.cache()
cached.count()
cached.take(10)
调用count时会导致第一次计算RDD,然后又需要计算take的动作,调用take时, 访问的是已经缓存好的元素,不需要再做计算。

2016年1月29日星期五

Mac中运行shell脚本command not found问题

写了一个a.sh文件:
#!/bin/bash
echo "hello"

通过 bash a.sh 或者 sh a.sh 执行都没有问题。

但 sudo ./a.sh 执行的时候报下面的错:
sudo: ./a.sh: command not found

解决方法,给该文件添加执行权限:
sudo chmod a+x a.sh
完成。

使用grep、sed、awk、sort统计日志文件中的字段

遇到这样一个需求,统计hdfs中log文件中的某个字段,log文件每一行格式如下:
{"msgid":"478721ef-ff6e-42b1-a2fb-97bba74c7bac","request_json":"{\"address\":\"中国,山东,临沂,罗庄,,,35.01737326529004,118.29531628357033\",\"appkey\":\"com.google\",\"channel\":\"aw_sdk\",\"device_id\":\"b61f0da076b9a88547c3b790014bd21d\",\"msg_id\":\"478721ef-ff6e-42b1-a2fb-97bba74c7bac\",\"output\":\"\",\"query\":\"on_peer_connected\",\"query_type\":\"event\",\"remote_ip\":\"\",\"task\":\"\",\"user_id\":\"b61f0da076b9a88547c3b790014bd21d\",\"version\":\"\",\"watch_build\":\"LHA72H\",\"watch_device_id\":\"7c0f71560710fe730e9b8d08ab7b7b00\"}","status":"success","msg_type":"event","lng":"118.295","wechat_user_id":"3790728","deviceid":"b61f0da076b9a88547c3b790014bd21d","qa_classification":"","qa_result":"{}","id":"56741496","content":"on_peer_connected","speech_id":"NULL","updated_at":"2015-10-08 15:27:43","wechat_app_id":"62","address":"中国,山东,临沂,罗庄,,,35.01737326529004,118.29531628357033","created_at":"2015-10-08 15:27:43","historical":"NULL","lat":"35.0174"}

需求是统计所有不同的watch_build的个数,一个可行的方法是直接使用grep先过滤出含有watch_build字段的log,然后sed截取watch_build,最后awk计算求和:
hdfs dfs -cat /data/log/offline/process/weiyuyi/2016/01/26/* | grep watch_build | sed 's/\(.*\)\(watch_build\)\\":\\"\([^\]*\)\(.*\)/\2:\3/g' | awk 'BEGIN{FS=":"} {a[$2]++;} END {for (i in a) print i ", " a[i];}'

或者使用sort,可以不用awk:
hdfs dfs -cat /data/log/offline/process/weiyuyi/2016/01/26/* | grep watch_build | sed 's/\(.*\)\(watch_build\)\\":\\"\([^\]*\)\(.*\)/\2:\3/g' | sort | uniq -c | sort -n -r

sed简明教程:link
awk简明教程:link

一个sed的简单例子,使用sed提取子字符串:
  testchenxiaoyuage20xxx,提取chenxiaoyu和20,格式为chenxiaoyu:20
  echo "testchenxiaoyuage20xxx" | sed 's/.*\(chenxiaoyu\)age\([0-9]*\).*/\1:\2/g'
  其中:
    .* 表示匹配任意文本;
    被 \( 和 \) 之间括起来的内容被自动按顺序编上了号,后面可以使用 \1 \2 等等来使用;
    /g表示一行上的替换所有匹配。

2016年1月28日星期四

ubuntu安装samba服务

apt-get install samba

vim /etc/samba/smb.conf,在最后加上以下配置,设置共享目录:
[share]
  path = your directory path
  browseable = yes
  writable = yes

添加samba用户:
useradd xxx
passwd xxx
smbpasswd -a xxx
如果已经有xxx用户,只需要smbpasswd -a即可。

重启samba服务:restart smbd,完成。

windows中开启ssh服务

提供思路,具体过程以后更新。

安装cygwin,安装过程中选择安装ssh,进行一些配置,完成。

Mac中解决LaTeX Error: File `lastpage.sty' not found问题

原因是在tex文件中使用了lastpage包,但是我只安装的basic版本的tex中没有这个包(link),所以需要另行安装。

在命令行中执行以下命令:
sudo tlmgr update --self
sudo tlmgr install lastpage

关于安装texlive-latex-extra,参考:link.

问题解决后,又遇到LaTeX Error: File `sectsty.sty' not found的问题,同理,在命令行中执行以下命令:
sudo tlmgr update --self  // 如果前面update过了这里不用再update
sudo tlmgr install sectsty

2016年1月27日星期三

Scala格式化数字输出

".3f".format(1.23456)  // 1.234

import java.text.DecimalFormat
val formatter = new DecimalFormat("#.###")
formatter.format(1)  // 1
formatter.format(1.34)  // 1.34
formatter.format(4.toFloat / 3)  // 1.333

2016年1月24日星期日

2016年1月22日星期五

在Sublime Text中使用Markdown

Markdown是一种简单的轻量级标记语言,一般用来写md文件。

在Sublime Text中使用Markdown
只需要安装Markdown Preview插件即可,ctrl+b 编译文件,编译完成后会生成一个html文件。

Markdown语言介绍
[ 转自http://www.jianshu.com/p/q81RER ]
标题:
# 一级标题
## 二级标题
### 三级标题
#### 四级标题
##### 五级标题
###### 六级标题
无序列表:
- 文本1
- 文本2
- 文本3
有序列表:
1. 文本1
2. 文本2
3. 文本3
链接:
[chenxiaoyu](http://jschenxiaoyu.blogspot.com)
在新标签页打开,只需要在后面再加上{:target="_blank"}即可。

图片:
![xxx](http://ww2.sinaimg.cn/square/83d79d5cjw8ew9f43d6pvj20hs0hs74y.jpg)
引用:
> 一盏灯, 一片昏黄; 一简书, 一杯淡茶。 守着那一份淡定, 品读属于自己的寂寞。 保持淡定, 才能欣赏到最美丽的风景! 保持淡定, 人生从此不再寂寞。
粗体(*)和斜体(**):
*一盏灯*, 一片昏黄;**一简书**, 一杯淡茶。 
表格:
| Tables        | Are           | Cool  |
| ------------- |:-------------:| -----:|
| col 3 is      | right-aligned | $1600 |
| col 2 is      | centered      |   $12 |
| zebra stripes | are neat      |    $1 |
TablesAreCool
col 3 isright-aligned$1600
col 2 iscentered$12
zebra stripesare neat$1

显示Latex:
![][1]
[1]: http://latex.codecogs.com/gif.latex?\prod{n_i}+1

分割线:
三个或更多的-_*,必须单独一行,可含空格
---

引用:
> 引用
>> 引用中的引用

代码格式:
`code`

代码块:
每行文字前加4个空格或者1个tab
和```效果一样

注释:
<!-- 注释 -->

root用户ssh登陆Permission denied, please try again.

vim /etc/ssh/sshd_config
将PermitRootLogin without-password改为PermitRootLogin yes
restart ssh,完成。

Mac和VirtualBox网络互访

在VirtualBox中打开偏好设置,选择网络,新建一个仅主机(Host-Only)网络,双击vboxnet0,设置网段,默认为192.168.56.1。

设置虚拟机,在网络选项中启用网卡2的网络连接,连接方式选择仅主机(Host-Only)适配器,确定,启动虚拟机。

2016年1月21日星期四

blade编译中collect2: ld returned 1 exit status问题

我是在虚拟机中编译的,遇到的问题比较奇怪,只有collect2: ld returned 1 exit status这个错误信息,没有其他提示。
原因是虚拟机的硬盘空间不够了,新加载了一个硬盘(参考链接:link),问题解决。

VirtualBox扩展虚拟机硬盘

参考链接:link.

选择相应的虚拟机,点击设置,选择左侧的存储,添加一个新的SATA控制器,启动虚拟机。

cd /dev,会发现多了一个sdb,fdisk  ./sdb,进入磁盘管理器。

输入命令p查看当前盘状态,输入命令n创建一个新的分区,有两个选项:e(扩展分区)和p(主分区),选择p分配区号(1到4中选)
Command (m for help): n
Partition type:
   p   primary (0 primary, 0 extended, 4 free)
   e   extended
Select (default p): p
Partition number (1-4, default 1):
Using default value 1
First sector (2048-20971519, default 2048):
Using default value 2048
Last sector, +sectors or +size{K,M,G} (2048-20971519, default 20971519):
Using default value 20971519
输入w命令保存退出。

在硬盘上建立文件系统:mkfs -t ext4 /dev/sdb1

挂载文件系统,我直接挂在了/mnt目录下:mount /dev/sdb1 /mnt
设置开机自动挂载:vim /etc/fstab,在最后增加/dev/sdb1 /mnt ext4 defaults 0 0
完成。

Mac添加ll命令,并使ls命令结果着色

vim ~/.bashrc,在最后加上:
alias ls='ls -G'
alias ll='ls -l'
alias la='ls -a'

或者着色直接可以export CLICOLOR=1

vim ~/.bash_profile,在最后加上:
source ~/.bashrc
完成。

2016年1月20日星期三

解决blade编译时/usr/bin/ld: cannot find -ljvm的问题

解决方法:
系统没有找到libjvm.so文件,而该文件在/usr/lib/jvm/java-7-openjdk-amd64/jre/lib/amd64/server目录下。如果没有,需要先安装jdk:apt-get install openjdk-7-jdk。

cd /usr/lib
ln -sv jvm/java-7-openjdk-amd64/jre/lib/amd64/server/libjvm.so libjvm.so
在/usr/lib中增加了libjvm.so,解决。

2016年1月19日星期二

2016年1月18日星期一

Source Insight中解决C++无法解析proto文件的问题

选择Options -> Preferences...,在Languages标签中双击C++ Language,点击Custom Parsing,然后Add一个Class,如图所示:
内容如下:
Namespace    ^package\w+\([a-zA-Z0-9_]+\)
Class    ^message\w+\([a-zA-Z0-9_]+\)
点击确定,re-parse project。
正则表达式参考:link.

选择Options -> Document Options...,在C++ Source File的File filter中增加*.proto,完成。

这个方法只能将就用,遇到 :: 不能解决。

现在看来,感觉也没什么卵用,直接把proto文件编译出来就可以了。

2016年1月15日星期五

Spark DataFrame的join操作

case class App(id: Int, name: String)
val data1 = sc.parallelize(Array((1, "a"), (2, "b"), (3, "c")))
val df1 = data.map { case (id, name) => App(id, name) }.toDF
val data2 = sc.parallelize(Array((1, "A"), (3, "B"), (5, "C")))
val df2 = data.map { case (id, name) => App(id, name) }.toDF

df1.show()
+---+----+
| id|name|
+---+----+
|  1|   a|
|  2|   b|
|  3|   c|
+---+----+

df2.show()
+---+----+
| id|name|
+---+----+
|  1|   A|
|  3|   B|
|  5|   C|
+---+----+

df1.join(df2)  // Cartesian join

df1.join(df2, "id")
+---+----+----+
| id|name|name|
+---+----+----+
|  1|   a|   A|
|  3|   c|   B|
+---+----+----+

df1.join(df2, df1("id") === df2("id")).show()
+---+----+---+----+
| id|name| id|name|
+---+----+---+----+
|  1|   a|  1|   A|
|  3|   c|  3|   B|
+---+----+---+----+

df1.join(df2, df1("id") === df2("id")).drop(df2("id")).show()
+---+----+----+
| id|name|name|
+---+----+----+
|  1|   a|   A|
|  3|   c|   B|
+---+----+----+

MySQL的基本操作

Please see this doc.

Spark SQL中DataFrame的几种写入模式

dataFrame.write.mode("xxx")进行设置

append
不改变表中已经存在记录,将新纪录写入。

overwrite
原来的记录全部删除,只有增加的记录。
举个例子:如果原来的表中有三个字段a, b, c,Overwrite的数据中只有两个字段a, b,那么原来c字段就没有了,慎用。

error
如果已经存在记录,抛出异常。

ignore
如果有已经存在的记录,DataFrame中的数据全部不会写入。

Spark SQL

关于Spark SQL,参考:link.

如果遇到 java.sql.SQLException: No suitable driver found for jdbc:mysql 问题,增加以下代码Class.forName("com.mysql.jdbc.Driver"),参考链接:link.

运行上一句代码时会出现 spark java.lang.ClassNotFoundException: com.mysql.jdbc.Driver 错误,需要设置jar包的路径指向mysql-connector-java-5.1.38-bin.jar:
./spark-submit --jars <path to jar>
如果在spark-shell或者standalone模式中运行,同样用--jars参数指定mysql-connector-java-5.1.38-bin.jar的路径。

如果不起作用的话,同时加入--driver-class-path <path to jar>设置。
如果再不行,再加上--conf spark.executor.extraClassPath=<path to jar>以及--conf spark.driver.extraClassPath=<path to jar>设置。参考链接:link.

2016年1月5日星期二

Spark读取jar包中的文件

直接附上我的示例代码:
package com.mobvoi.app.recommendation.data

import java.io.InputStream

import scala.io.Source.fromInputStream

trait AppNameData extends Serializable {
  @transient private val stream: InputStream = getClass.getResourceAsStream("/app_name.txt")

  private val appIdName = fromInputStream(stream).getLines.toArray

  /** Param for app id and app name map. */
  private[recommendation] val appIdNameMap = appIdName.map { x =>
    val str = x.split("   ")
    (str(0).trim, str(1).trim)
  }.toMap

  /** Param for app name and app id map. */
  private[recommendation] val appNameIdMap = appIdName.map { x =>
    val str = x.split("   ")
    (str(1).trim, str(0).trim)
  }.toMap
}