java 获取对象的所有属性和它们的值

下面我们展示如何获取对象的所有属性和它们的值,首先我们新建一个实体类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
/**
*
* <p>
* <b>User</b> 是 测试用的类
* </p>
*
* @author <a href="mailto:wentian.he@qq.com">hewentian</a>
* @date 2017年11月10日 上午12:19:18
* @since JDK 1.8
*
*/
public class User {
/** id */
private Integer id;

/** 姓名 */
private String name;

/** 年龄 */
private Integer age;

public User(Integer id, String name, Integer age) {
super();
this.id = id;
this.name = name;
this.age = age;
}

public Integer getId() {
return id;
}

public void setId(Integer id) {
this.id = id;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public Integer getAge() {
return age;
}

public void setAge(Integer age) {
this.age = age;
}
}

这里我们用到了apache提供的工具包commons-beanutils-1.9.3.jar,详细代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43

import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.beanutils.PropertyUtils;

/**
*
* <p>
* <b>GetPropertyAndValue</b> 是 获取对象的所有属性和它们的值
* </p>
*
* @author <a href="mailto:wentian.he@qq.com">hewentian</a>
* @date 2017年11月10日 上午12:20:09
* @since JDK 1.8
*
*/
public class GetPropertyAndValue {
public static void main(String[] args) {
User user = new User(1, "Tim Ho", 23);

List<String> properties = new ArrayList<String>();

System.out.println("获取所有属性");
PropertyDescriptor[] pds = PropertyUtils.getPropertyDescriptors(user.getClass());
for (PropertyDescriptor pd : pds) {
System.out.println(pd.getName() + "\t" + pd.getPropertyType());
properties.add(pd.getName());
}

System.out.println("\n根据属性获取这个属性的值");
properties.stream().forEach(p -> {
try {
Object value = PropertyUtils.getProperty(user, p);
System.out.println(p + "\t" + value);
} catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
e.printStackTrace();
}
});
}
}

输出结果如下:

1
2
3
4
5
6
7
8
9
10
11
获取所有属性
name class java.lang.String
id class java.lang.Integer
class class java.lang.Class
age class java.lang.Integer

根据属性获取这个属性的值
name Tim Ho
id 1
class class com.hewentian.User
age 23

end.

solr 学习笔记

HttpSolrClient

HttpSolrClient 使用 HTTPClient 和 solr 服务器进行通信。

1
2
3
4
5
6
7
8
import org.apache.solr.client.solrj.impl.HttpSolrClient;

String baseSolrUrl = "http://localhost:8983/solr/";

HttpSolrClient solrClient = new HttpSolrClient.Builder().withBaseSolrUrl(baseSolrUrl).build();
solrClient.setConnectionTimeout(1000);
solrClient.setDefaultMaxConnectionsPerHost(100);
solrClient.setMaxTotalConnections(100);

HttpSolrClient 是线程安全的,建议重复使用 HttpSolrClient 实例。

EmbeddedSolrServer

EmbeddedSolrServer 提供和 HttpSolrClient 相同的接口,它不需要http连接。如果,你使用的是一个本地的 solrServer 的话,这是一个不错的选择。

1
2
3
4
5
6
7
8
9
import org.apache.solr.client.solrj.embedded.EmbeddedSolrServer;
import org.apache.solr.core.CoreContainer;

System.setProperty("solr.solr.home", "/home/hewentian/ProjectD/solr-6.5.0/server/solr");

CoreContainer coreContainer = new CoreContainer("/home/hewentian/ProjectD/solr-6.5.0/server/solr");
coreContainer.load(); // don't forge to invoke this method since solr 4.4.0

EmbeddedSolrServer embeddedSolrServer = new EmbeddedSolrServer(coreContainer, coreName);

通过 POJO 方式往 Solr 中添加 doc 时,要使用 注解@org.apache.solr.client.solrj.beans.Field,@Field 可以被用在域上,或者是setter方法上。如果一个域的名称跟bean的名称是不一样的,那么在java注释中填写别名,具体的,可以参照下面的例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class User {
/** 用户id */
@Field
private String id;

/** 名字 */
@Field
private String name;

/** 年龄 */
@Field
private Integer age;

// getter setter method
}

当将一个 doc 往 solr 中添加之后,要记得调用 commit 方法,当然,如果在 solrconfig.xml 中有配置硬/软提交的,可以省略

1
2
3
4
5
SolrClient solrClient = createSolrClient(baseSolrUrl);
UpdateResponse response = solrClient.addBean(collection, user);

solrClient.commit(collection);
solrClient.close();

Group 分组划分结果,返回的是分组结果;
Facet 分组统计,侧重统计,返回的是分组后的数量;
下面分别说下

Facet查询

进行Facet查询需要在请求参数中加入”facet=on”或者”facet=true”只有这样Facet组件才起作用.
搜索结果按照Facet的字段分组并统计

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
SolrQuery solrQuery = new SolrQuery();
solrQuery.setQuery("老师");
solrQuery.setFacet(true);
solrQuery.setFacetMinCount(1); // 统计结果大于 1 的才会返回
solrQuery.setFacetLimit(10); // 对于每一个 field 最多返回 10 个结果
solrQuery.addFacetField("age", "name");
solrQuery.setRows(0); // 设置返回结果条数,如果分组查询,就设置为0

QueryResponse queryResponse = SolrUtils.getQueryResponse(baseSolrUrl, collection, solrQuery);
List<FacetField> facetFields = queryResponse.getFacetFields();
facetFields.stream().forEach(ff -> {
ff.getValues().stream().forEach(c -> {
System.out.println(c.getName() + ", " + c.getCount());
});
System.out.println();
});

///~: output
50, 3
20, 2
40, 1

陈六, 2
张三, 1
李七, 1
李四, 1
王五, 1

facet的参数见solr官方wiki http://wiki.apache.org/solr/SimpleFacetParameters

facet 参数字段要求:
1.字段必须被索引
2.facet=on 或 facet=true

1.facet.field
分组的字段
2.facet.prefix
表示Facet字段前缀
3.facet.limit
Facet字段返回条数
4.facet.offict
开始条数,偏移量,它与facet.limit配合使用可以达到分页的效果
5.facet.mincount
Facet字段最小count,默认为0
6.facet.missing
如果为on或true,那么将统计那些Facet字段值为null的记录
7.facet.method
取值为enum或fc,默认为fc, fc表示Field Cache
8.facet.enum.cache.minDf
当facet.method=enum时,参数起作用,文档内出现某个关键字的最少次数

Group查询

分组统计查询不同于分组统计(Facet),facet只是简单统计记录数,并不能为每组数据返回实际的数据回来,solr提供的grouping查询能够解决这一问题,也就是说,他除了能分组外,还能把每组数据返回来。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
SolrQuery solrQuery = new SolrQuery();
solrQuery.setQuery("*:*");
solrQuery.set(GroupParams.GROUP, true);
solrQuery.set(GroupParams.GROUP_FIELD, "age", "name");
solrQuery.set(GroupParams.GROUP_LIMIT, 3);
solrQuery.set(GroupParams.GROUP_FORMAT, "grouped");
solrQuery.set(GroupParams.GROUP_MAIN, false);
solrQuery.set(GroupParams.GROUP_TOTAL_COUNT, true);
solrQuery.set(GroupParams.GROUP_SORT, "age asc");

QueryResponse queryResponse = SolrUtils.getQueryResponse(baseSolrUrl, collection, solrQuery);
// 通过GroupResponse获取GroupCommand,进而通过GroupCommand获取Group,而Group又可以获得SolrDocumentList
GroupResponse groupResponse = queryResponse.getGroupResponse();
List<GroupCommand> groupCommands = groupResponse.getValues();
for (GroupCommand gc : groupCommands) {
System.out.println("\n########## group name: " + gc.getName());
// 只有设置 GroupParams.GROUP_TOTAL_COUNT 这里 getNGroups 才有效果
System.out.println("########## Num of Groups Found: " + gc.getNGroups());
System.out.println("########## Num of documents Found: " + gc.getMatches());

List<Group> groups = gc.getValues();
for (Group g : groups) {
SolrDocumentList solrDocumentList = g.getResult();
System.out.println("\n########## group name: " + gc.getName() + ", groupValue: " + g.getGroupValue()
+ ", Num of Documents in this group: " + solrDocumentList.getNumFound());
if (CollectionUtils.isNotEmpty(solrDocumentList)) {
for (SolrDocument sd : solrDocumentList) {
System.out.println(sd);
}
}
}
}

solr建立索引的过程和查询过程

solr索引建立:

第一步:solr会对句子进行空格分隔,比如对 JAVA is a kind of computer language 分词,分为JAVA,is,a,kind,of,computer,language;

第二步:solr会对上面分出来的词,去掉停用词,这里比如a,is;

第三部:solr会对上面分出来的英文都转化为小写 java,kind,of,computer,language。

solr查询过程:

第一步:同索引过程;

第二步:同索引过程;

第三部:同索引过程;

最后分词匹配成功,那么索引的那句话就会被查询出来,这里需要注意:索引和查询的分词器必须使用一样的!!!

下面说说Solr基础

部分内容转载自如下网址,详情请参阅:
http://blog.csdn.net/awj3584/article/details/16963525
https://lucene.apache.org/solr/guide/
以下部分为抄录内容

types 部分

是一些常见的可重用定义,定义了 Solr(和 Lucene)如何处理 Field。也就是添加到索引中的xml文件属性中的类型,如int、text、date等.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<fieldType name="string" class="solr.StrField" sortMissingLast="true"/>
<fieldType name="boolean" class="solr.BoolField" sortMissingLast="true"/>
<fieldType name="int" class="solr.TrieIntField" precisionStep="0" positionIncrementGap="0"/>
<fieldType name="text_general" class="solr.TextField" positionIncrementGap="100">
<analyzer type="index">
<tokenizer class="solr.StandardTokenizerFactory"/>
<filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.txt" enablePositionIncrements="true" />
<filter class="solr.LowerCaseFilterFactory"/>
</analyzer>
<analyzer type="query">
<tokenizer class="solr.StandardTokenizerFactory"/>
<filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.txt" enablePositionIncrements="true" />
<filter class="solr.SynonymFilterFactory" synonyms="synonyms.txt" ignoreCase="true" expand="true"/>
<filter class="solr.LowerCaseFilterFactory"/>
</analyzer>
</fieldType>

参数说明:

属性 描述
name 标识而已
class 和其他属性决定了这个fieldType的实际行为。
sortMissingLast 设置成true没有该field的数据排在有该field的数据之后,而不管请求时的排序规则, 默认是设置成false。
sortMissingFirst 跟上面倒过来呗。 默认是设置成false
analyzer 字段类型指定的分词器
type 当前分词用用于的操作.index代表生成索引时使用的分词器query代码在查询时使用的分词器
tokenizer 分词器类
filter 分词后应用的过滤器 过滤器调用顺序和配置相同.

fileds

是你添加到索引文件中出现的属性名称,而声明类型就需要用到上面的types

1
2
3
4
5
6
7
8
9
<field name="id" type="string" indexed="true" stored="true" required="true" multiValued="false"/>
<field name="path" type="text_smartcn" indexed="false" stored="true" multiValued="false" termVector="true" />
<field name="content" type="text_smartcn" indexed="false" stored="true" multiValued="false" termVector="true"/>
<field name ="text" type ="text_ik" indexed ="true" stored ="false" multiValued ="true"/>
<field name ="pinyin" type ="text_pinyin" indexed ="true" stored ="false" multiValued ="false"/>
<field name="_version_" type="long" indexed="true" stored="true"/>
<dynamicField name="*_i" type="int" indexed="true" stored="true"/>
<dynamicField name="*_l" type="long" indexed="true" stored="true"/>
<dynamicField name="*_s" type="string" indexed="true" stored="true" />

field: 固定的字段设置
dynamicField: 动态的字段设置,用于后期自定义字段,*号通配符.例如: test_i就是int类型的动态字段.
还有一个特殊的字段copyField,一般用于检索时用的字段这样就只对这一个字段进行索引分词就行了copyField的dest属性如果有多个source一定要设置multiValued=true,否则会报错的

1
2
3
4
5
<copyField source="content" dest="pinyin"/>
<copyField source="content" dest="text"/>
<copyField source="pinyin" dest="text"/>

<field name="text" type="text_general" indexed="true" stored="false" multiValued="true"/>

字段属性说明:

属性 描述
name 字段类型名
class java类名
indexed 缺省true。 说明这个数据应被搜索和排序,如果数据没有indexed,则stored应是true。
stored 缺省true。说明这个字段被包含在搜索结果中是合适的。如果数据没有stored,则indexed应是true。
omitNorms 字段的长度不影响得分和在索引时不做boost时,设置它为true。一般文本字段不设置为true。
termVectors 如果字段被用来做more like this 和highlight的特性时应设置为true。
compressed 字段是压缩的。这可能导致索引和搜索变慢,但会减少存储空间,只有StrField和TextField是可以压缩,这通常适合字段的长度超过200个字符。
multiValued 字段多于一个值的时候,可设置为true。
positionIncrementGap 和multiValued一起使用,设置多个值之间的虚拟空白的数量

注意:version 是一个特殊字段,不能删除,是记录当前索引版本号的.

uniqueKey: 唯一键,这里配置的是上面出现的fileds,一般是id、url等不重复的。在更新、删除的时候可以用到。
defaultSearchField: 默认搜索属性,如q=solr就是默认的搜索那个字段(默认搜text,其他字段的值会copy到这个field)
solrQueryParser: 查询转换模式,是并且还是或者(AND/OR必须大写)

solr配置solrconfig.xml

对于我的机器来说,是在以下目录:/home/hewentian/ProjectD/solr-6.5.0/server/solr/mysqlCore/conf/solrconfig.xml

索引indexConfig

Solr 性能因素,来了解与各种更改相关的性能权衡。 下表概括了可控制 Solr 索引处理的各种因素:

属性 描述
useCompoundFile 通过将很多 Lucene 内部文件整合到一个文件来减少使用中的文件的数量。这可有助于减少 Solr 使用的文件句柄数目,代价是降低了性能。除非是应用程序用完了文件句柄,否则 false 的默认值应该就已经足够。
ramBufferSizeMB 在添加或删除文档时,为了减少频繁的更些索引,Solr会选缓存在内存中,当内存中的文件大于设置的值,才会更新到索引库。较大的值可使索引时间变快但会牺牲较多的内存。
maxBufferedDocs 同 ramBufferSizeMB,如两个值同时设置,满足一个就会进行刷新索引.
mergeFactor 决定低水平的 Lucene 段被合并的频率。较小的值(最小为 2)使用的内存较少但导致的索引时间也更慢。较大的值可使索引时间变快但会牺牲较多的内存。
maxIndexingThreads 是indexWriter生成索引时使用的最大线程数
unlockOnStartup unlockOnStartup 告知 Solr 忽略在多线程环境中用来保护索引的锁定机制。在某些情况下,索引可能会由于不正确的关机或其他错误而一直处于锁定,这就妨碍了添加和更新。将其设置为 true 可以禁用启动锁定,进而允许进行添加和更新。
lockType 1. single: 在只读索引或是没有其它进程修改索引时使用. 2. native: 使用操作系统本地文件锁,不能使用多个Solr在同一个JVM中共享一个索引. 3. simple :使用一个文本文件锁定索引.

查询配置query

属性 描述
maxBooleanClauses 最大的BooleanQuery数量. 当值超出时,抛出 TooManyClausesException.注意这个是全局的,如果是多个SolrCore都会使用一个值,每个Core里设置不一样的话,会使用最后一个的.
filterCache filterCache存储了无序的lucene document id集合,1.存储了filter queries(“fq”参数)得到的document id集合结果。2.还可用于facet查询。3. 如果配置了useFilterForSortedQuery,那么如果查询有filter,则使用filterCache。
queryResultCache 缓存搜索结果,一个文档ID列表
documentCache 缓存Lucene的Document对象,不会自热
fieldValueCache 字段缓存使用文档ID进行快速访问。默认情况下创建fieldValueCache即使这里没有配置。
enableLazyFieldLoading 若应用程序预期只会检索 Document 上少数几个 Field,那么可以将属性设置为 true。延迟加载的一个常见场景大都发生在应用程序返回和显示一系列搜索结果的时候,用户常常会单击其中的一个来查看存储在此索引中的原始文档。初始的显示常常只需要显示很短的一段信息。若考虑到检索大型 Document 的代价,除非必需,否则就应该避免加载整个文档。
queryResultWindowSize 一次查询中存储最多的doc的id数目.
queryResultMaxDocsCached 查询结果doc的最大缓存数量, 例如要求每页显示10条,这里设置是20条,也就是说缓存里总会给你多出10条的数据.让你点示下一页时很快拿到数据.
listener 选项定义 newSearcher 和 firstSearcher 事件,您可以使用这些事件来指定实例化新搜索程序或第一个搜索程序时应该执行哪些查询。如果应用程序期望请求某些特定的查询,那么在创建新搜索程序或第一个搜索程序时就应该反注释这些部分并执行适当的查询。
useColdSearcher 是否使用冷搜索,为false时使用自热后的searcher
maxWarmingSearchers 最大自热searcher数量

删除索引

删除索引可以通过两种方式操作,一种是通过文档ID进行删除, 另一种是通过查询到的结果进行删除.

1
2
3
4
5
6
7
8
通过ID删除方式代码:
solrClient.deleteById(id);

//或是使用批量删除
solrClient.deleteById(ids);

通过查询删除方式代码:
solrClient.deleteByQuery("*:*"); // ”*:*” 就查询所有内容的, 这样就删除了所有文档索引

优化索引

优化Lucene 的索引文件以改进搜索性能。索引完成后执行一下优化通常比较好。如果更新比较频繁,则应该在使用率较低的时候安排优化。一个索引无需优化也可以正常地运行。优化是一个耗时较多的过程。

1
solrClient.optimize(); // 不要频繁的调用, 尽量在无人使用时调用

查询参数

名称 描述
q 查询字符串,必须的
fq filter query。使用Filter Query可以充分利用Filter Query Cache,提高检索性能。作用:在q查询符合结果中同时是fq查询符合的,例如:q=mm&fq=date_time:[20081001 TO 20091031],找关键字mm,并且date_time是20081001到20091031之间的
fl field list。指定返回结果字段。以空格“ ”或逗号“,”分隔
start 用于分页定义结果起始记录数,默认为0
rows 用于分页定义结果每页返回记录数,默认为10
sort 排序,格式: sort=<field name>+<desc|asc>[,<field name>+<desc|asc>]… 。示例:(inStock desc, price asc)表示先 “inStock” 降序, 再 “price” 升序,默认是相关性降序。
df 默认的查询字段,一般默认指定
q.op 覆盖schema.xml的defaultOperator(有空格时用”AND”还是用”OR”操作逻辑),一般默认指定。必须大写
wt writer type。指定查询输出结构格式,默认为“xml”。在solrconfig.xml中定义了查询输出格式:xml、json、python、ruby、php、phps、custom
qt query type,指定查询使用的Query Handler,默认为“standard”
explainOther 设置当debugQuery=true时,显示其他的查询说明
defType 指定用于处理查询语句(参数q的内容)的查询解析器,eg:defType=lucene
timeAllowed 设置查询超时时间
omitHeader 设置是否忽略查询结果返回头信息,默认为“false”
indent 返回的结果是否缩进,默认关闭,用 indent=true|on 开启,一般调试json,php,phps,ruby输出才有必要用这个参数
version 查询语法的版本,建议不使用它,由服务器指定默认值
debugQuery 设置返回结果是否显示Debug信息

查询语法

  1. 匹配所有文档::

  2. 强制、阻止和可选查询:
    1)Mandatory:查询结果中必须包括的(for example, only entry name containing the word make)
    Solr/Lucene Statement:+make, +make +up ,+make +up +kiss
    2)prohibited:(for example, all documents except those with word believe)
    Solr/Lucene Statement:+make +up -kiss
    3)optional:Solr/Lucene Statement:+make +up kiss

  3. 布尔操作:AND、OR和NOT布尔操作(必须大写)与Mandatory、optional和prohibited相似。
    1)make AND up = +make +up :AND左右两边的操作都是mandatory
    2)make || up = make OR up=make up :OR左右两边的操作都是optional
    3)+make +up NOT kiss = +make +up –kiss
    4)make AND up OR french AND Kiss不可以达到期望的结果,因为AND两边的操作都是mandatory的。

  4. 子表达式查询(子查询):可以使用“()”构造子查询。
    示例:(make AND up) OR (french AND Kiss)

  5. 子表达式查询中阻止查询的限制:
    示例:make (-up):只能取得make的查询结果;要使用make (-up :)查询make或者不包括up的结果。

  6. 多字段fields查询:通过字段名加上分号的方式(fieldName:query)来进行查询
    示例:entryNm:make AND entryId:3cdc86e8e0fb4da8ab17caed42f6760c

  7. 通配符查询(wildCard Query):
    1)通配符?和*:“*”表示匹配任意字符;“?”表示匹配出现的位置。
    示例:ma?*(ma后面的一个位置匹配),ma??*(ma后面两个位置都匹配)
    2)查询字符必须要小写:+Ma +be**可以搜索到结果;+Ma +Be**没有搜索结果.
    3)查询速度较慢,尤其是通配符在首位:主要原因一是需要迭代查询字段中的每个term,判断是否匹配;二是匹配上的term被加到内部的查询,当terms数量达到1024的时候,查询会失败。
    4)Solr中默认通配符不能出现在首位(可以修改QueryParser,设置setAllowLeadingWildcard为true)

  8. 模糊查询、相似查询:不是精确的查询,通过对查询的字段进行重新插入、删除和转换来取得得分较高的查询解决(由Levenstein Distance Algorithm算法支持)。
    1)一般模糊查询:示例:make-believ~
    2)门槛模糊查询:对模糊查询可以设置查询门槛,门槛是0~1之间的数值,门槛越高表面相似度越高。示例:make-believ~0.5、make-believ~0.8、make-believ~0.9

  9. 范围查询(Range Query):Lucene支持对数字、日期甚至文本的范围查询。结束的范围可以使用“*”通配符。
    示例:
    1)日期范围(ISO-8601 时间GMT):sa_type:2 AND a_begin_date:[1990-01-01T00:00:00.000Z TO 1999-12-31T24:59:99.999Z]
    2)数字:salary:[2000 TO *]
    3)文本:entryNm:[a TO a]

  10. 日期匹配:YEAR, MONTH, DAY, DATE (synonymous with DAY) HOUR, MINUTE, SECOND, MILLISECOND, and MILLI (synonymous with MILLISECOND)可以被标志成日期。
    示例:
    1)r_event_date:[* TO NOW-2YEAR]:2年前的现在这个时间
    2)r_event_date:[* TO NOW/DAY-2YEAR]:2年前前一天的这个时间

  11. solr的查询语句支持C语言格式的注释。
    "jakarta apache" /* this is a comment in the middle of a normal query string */ OR jakarta

  12. + - && || ! ( ) { } [ ] ^ " ~ * ? : / 这些字符在solr中具有特殊的含义,如果要使用这么字符本身含义,需要利用反斜杠进行转义,比如: \(1\+1\):2

  13. solr的查询字符串q中的多个关键字之间默认的关系是 OR
    例如:红旗 中国 ,代表:红旗 OR 中国

  14. 若要搜寻交集结果,请在词与词间加上大写 “AND” 或 “+” (不包含”号).
    例如: text:总统府 AND text:邮局

    +text:总统府 +text:邮局

    name:总统府 AND tel:23xxxxxx3

    name: ( +总统府 +邮局)

  15. 排除查询
    在要排除的词前加上 “-” (不包含”号) 号
    例如: 总统府 -邮局
    搜寻结果不会有包含邮局的词的结果在内

  16. 增加权重: 如要搜寻 “中华 加油站”(不包含”号) 但因为回传太多笔资料内有 “中华”(不包含”号) 或 “加油站”(不包含”号) 的结果,
    所以想要把有包含 “加油站”(不包含”号)的数据往前排,可使用 “^”(不包含”号)符号在后面加上愈增加的权重数,
    像是 “2″,则可以这样做:
    中华 加油站^2
    会同时搜寻含有中华或加油站的结果,并把加油站这个词加权所以搜寻时会先判断加油站这一个词在
    搜寻结果中的比重,甚至假设一笔数据内加油站出现过两次以上的就更加会有优先权.

标准查询操作符

参数 描述
: 指定要查找的字段,比如:title:“The Right Way” AND text:go
匹配单一字符,比如: te?t匹配test/text
* 匹配0或多个字符,比如:tes*匹配test/testing/tester
~ 基于编辑距离的模糊查询,比如:roam~匹配roams/foam/foams/roam. roam~1(指定距离必须是1)匹配roams/foam,但不会匹配foams
~n 邻近查询,查找相隔一定距离的单词,比如:”jakarta apache”~10(相隔10个单词) (下面会详细说明~~n的区别)
TO 范围查询,{}不包含边界,[]包含边界,比如:title:{Aida TO Carmen}
^ 加权因子,比如:jakarta^4 apache 查找结果中jakarta更相关, 看下面相关度的说明
^= 指定查询语句的score得分为常量,比如:(description:blue OR color:blue)^=1.0 text:shoes
AND(&&) 运算符两边的查询词同时出现 比如:”jakarta apache” AND “Apache Lucene”
OR 运算符两边的查询词至少一个出现, 默认运算符,比如 “jakarta apache” jakarta 等价于 “jakarta apache” OR jakarta
NOT(!) 运算符后面的查询词不出现,比如”jakarta apache” NOT “Apache Lucene”
+ 运算符后面的查询词出现(known as the “required” operator),比如+jakarta lucene查询必须包含jakarta,而lucene可以出现可不出现
- 不能包含运算符后面的查询词 “jakarta apache” -“Apache Lucene”
[] 包含范围边界
{} 不包含范围边界

模糊/编辑距离查询(对中文支持好像不太好,我在数字和英文上才测试成功)

对于很多搜索应用来说,很重要的功能是不仅仅需要精确匹配用户的文本内容。而且还允许一些灵活的变化,比如一些用户的拼写错误或相同单词的其它变体。Solr 通过基于 Damerau-Levenshtein 距离的编辑距离测量来支持这个功能,它将容忍 80% 以上的拼写错误。

Solr 提供的模糊编辑距离查询需要用到波浪符号(~):

查询语句: administrator~ 匹配: adminstrator, administrater, administratior,等
这个查询不仅匹配原始的关键字(administrator),还有其它与原始关键字有 2 个编辑距离的关键字。一个编辑距离表示增加,删除,取代或交换一个任意字符。关键字 adminstrator (在第六个字母出少了字符“i”)和原始关键字之间相差一个编辑距离,因为它删除了一个字符。同样 sadministrator 和原始关键字之间也是相差一个编辑距离,因为它在前面添加了一个字符。administratro 也与原始关键字有一个编辑距离,因为它将最后两个字符交换了顺序。

在编辑距离查询中也可以精确指定编辑距离:

查询语句:administrator~1 匹配一个编辑距离以内的内容。
查询语句:administrator~2 匹配两个编辑距离以内的内容(如果没有提供编辑距离的话,这个就是默认值)。
查询语句:administrator~N 匹配 N 个编辑距离以内的内容。
注意,任何编辑距离大于 2 的查询将会使查询速度变得很慢。如果编辑距离在 2 以内,那么将会使用很高效率的 Levenshtein 自动机(Levenshtein automaton),但是如果编辑距离大于 2,将会退回到更慢的编辑距离实现。

临近查询

在前面,我们看到了编辑距离查询是如何查找相似的关键字,而不是进行精确匹配。编辑距离的概念适用于关键字中字符的变换或短语中各个单词之间的变化。

如果你想要通过 Solr 的索引查询公司中所有员工的档案。一种方法是枚举出公司中所有可能的职位:

查询语句:”chief executive officer” OR “chief financial officer” OR “chief marketing officer” OR “chief technology officer” OR …

当然,这种查询的前提是你需要知道公司中所有可能的职位,这当然不现实。另外的一种解决方案是单独搜索每个关键字:

查询语句: chief AND officer
这将会匹配所有可能的用例,但是同时也会匹配所有包含了这两个关键字的文档。例如:One chief concern arising from the incident was the safety of the police officer on duty。这个文档明显不符合我们的要求,但是如果使用上面的查询语句,那么将会返回这个文档。

Solr 提供了解决这种问题的方案:临近查询。在上面的例子中,比较好的策略是请求 Solr 返回所有包含了关键字 chief 和关键字 officer 临近的文档。这可以通过下面的查询语句样例来实现:

查询语句: “chief officer”~1
解释:chief 和 officer 之间最多只能有一个距离
例子:”chief executive officer”, “chief financial officer”

查询语句:”chief officer”~2
解释:chief 和 officer 之间最多只能有两个编辑距离
例子:”chief business development officer”, “officer chief”

查询语句:”chief officer”~N
解释:查询 chief 和 officer 之间有 N 个编辑距离。

事实上,对短语进行精确匹配的查询语句 “chief development officer” 很容易改写成 “chief development officer”~0。这两个查询都返回相同的结果,因为在第二个查询语句中,编辑距离设置为 0,所以和精确查询得到的结果是相同的。这两种机制都需要使用到 Solr 中存储的关键字位置(前面的文章介绍过)来计算编辑距离。还有一点需要注意的是,临近查询并不是完全按照编辑距离的定义来进行查询,因为它的查询结果中,所有的关键字都必须存在。而编辑距离查询的定义中,可以对关键字进行删除和修改。

但是其它的编辑距离定义依旧保留,例如增加和换位。顺着这条线,你可能会注意到,你需要设置 2 进行临近查询的时候(”chief officer”~2)才能查询出文本 officer chief。这是因为第一次编辑将 chief 和 officer 修改成相同的位置;第二次编辑将 chief 才能将 chief 编辑到 officer 后面。这也再次说明了临近查询使用的并不是真正的编辑距离(在编辑距离中,位置互换的编辑距离只能算 1)。

模糊/编辑距离查询 和 临近查询 的区别

  1. 模糊/编辑距离查询 是对一个字符串进行查询;
  2. 临近查询 是对两个字符串进行查询,并且它们被”包围着

Solr文本匹配不同字段的相关度权重设置需要做如下设置:

1)启用edismax选项,在检索url上添加defType=edismax参数
2)设置q参数为搜索关键词,这里不要再写搜索表达式了
3)设置qf参数,指定不同字段的权重,例如:title^10 keywords^10 content^1 表示title字段的权重设置为10,keywords为10,content权重设置为1


solr删除数据的快捷方式

在solr的WEB客户端,访问你的索引库
1)documents type 选择 XML
2)documents 输入下面语句

1
2
<delete><query>*:*</query></delete>
<commit/>

点击Submit Document即可

filter query 的使用

如果要查询的结果中必须包含某些字段,则可以加上{fieldName}:{queryExpress}
例如email:*将获取结果中包含email字段的所有记录
如果不想包含某些字段则可以这样-email:*,在其前面加一个减号

solr 提交索引的三种方式

1.commit

通过api直接commit,这样性能比较差

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import org.apache.solr.client.solrj.SolrServerException;
import org.apache.solr.client.solrj.impl.HttpSolrClient;
import org.apache.solr.common.SolrInputDocument;

String baseSolrUrl = "http://localhost:8983/solr/";
HttpSolrClient solrClient = new HttpSolrClient.Builder().withBaseSolrUrl(baseSolrUrl).build();

SolrInputDocument solrInputDocument = new SolrInputDocument();
solrInputDocument.addField("id", "1");
solrInputDocument.addField("name", "Tim Ho");
solrInputDocument.addField("age", "23");

solrClient.add("mysqlCore", solrInputDocument);
solrClient.commit();

2.commitWithinMs

简单的说就是告诉solr在多少毫秒内提交,比如我指定commitWithinMs=10000,将会告诉solr在10s内提交我的document。

1
2
3
4
5
6
7
用法:
1.可以在add方法设置参数,比如:solrClient.add("mysqlCore", solrInputDocument, 10000);

2.UpdateRequest updateRequest = new UpdateRequest();
updateRequest.add(solrInputDocument);
updateRequest.setCommitWithin(10000);
updateRequest.process(solrClient, "mysqlCore");

参考:https://lucene.apache.org/solr/guide/6_6/updatehandlers-in-solrconfig.html

3.AutoCommit

参考:http://wiki.apache.org/solr/SolrConfigXml
例如,我的配置文件在 /home/hewentian/ProjectD/solr-6.5.0/server/solr/mysqlCore/conf/solrconfig.xml 中已有默认配置,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
<!-- The default high-performance update handler -->
<updateHandler class="solr.DirectUpdateHandler2">

<!-- Enables a transaction log, used for real-time get, durability, and
and solr cloud replica recovery. The log can grow as big as
uncommitted changes to the index, so use of a hard autoCommit
is recommended (see below).
"dir" - the target directory for transaction logs, defaults to the
solr data directory.
"numVersionBuckets" - sets the number of buckets used to keep
track of max version values when checking for re-ordered
updates; increase this value to reduce the cost of
synchronizing access to version buckets during high-volume
indexing, this requires 8 bytes (long) * numVersionBuckets
of heap space per Solr core.
-->
<updateLog>
<str name="dir">${solr.ulog.dir:}</str>
<int name="numVersionBuckets">${solr.ulog.numVersionBuckets:65536}</int>
</updateLog>

<!-- AutoCommit

Perform a hard commit automatically under certain conditions.
Instead of enabling autoCommit, consider using "commitWithin"
when adding documents.

http://wiki.apache.org/solr/UpdateXmlMessages

maxDocs - Maximum number of documents to add since the last
commit before automatically triggering a new commit.

maxTime - Maximum amount of time in ms that is allowed to pass
since a document was added before automatically
triggering a new commit.
openSearcher - if false, the commit causes recent index changes
to be flushed to stable storage, but does not cause a new
searcher to be opened to make those changes visible.

If the updateLog is enabled, then it's highly recommended to
have some sort of hard autoCommit to limit the log size.
-->
<autoCommit>
<maxTime>${solr.autoCommit.maxTime:15000}</maxTime>
<openSearcher>false</openSearcher>
</autoCommit>

<!-- softAutoCommit is like autoCommit except it causes a
'soft' commit which only ensures that changes are visible
but does not ensure that data is synced to disk. This is
faster and more near-realtime friendly than a hard commit.
-->

<autoSoftCommit>
<maxTime>${solr.autoSoftCommit.maxTime:-1}</maxTime>
</autoSoftCommit>

<!-- Update Related Event Listeners

Various IndexWriter related events can trigger Listeners to
take actions.

postCommit - fired after every commit or optimize command
postOptimize - fired after every optimize command
-->
<!-- The RunExecutableListener executes an external command from a
hook such as postCommit or postOptimize.

exe - the name of the executable to run
dir - dir to use as the current working directory. (default=".")
wait - the calling thread waits until the executable returns.
(default="true")
args - the arguments to pass to the program. (default is none)
env - environment variables to set. (default is none)
-->
<!-- This example shows how RunExecutableListener could be used
with the script based replication...
http://wiki.apache.org/solr/CollectionDistribution
-->
<!--
<listener event="postCommit" class="solr.RunExecutableListener">
<str name="exe">solr/bin/snapshooter</str>
<str name="dir">.</str>
<bool name="wait">true</bool>
<arr name="args"> <str>arg1</str> <str>arg2</str> </arr>
<arr name="env"> <str>MYVAR=val1</str> </arr>
</listener>
-->

</updateHandler>

1.硬提交是提交数据持久化到磁盘里面。不过,比较耗费机器资源,这样即使jvm崩溃或者宕机,也不影响这部分索引。

openSearcher: true 索引在searcher中可见, 但是也需要重新打开searcher才行。
openSearcher: false 索引在searcher中不可见。

按照下面的配置就会使用solr的自动硬提交功能,就不用我们自己手动提交。

1
2
3
4
5
6
7
8
9
10
<autoCommit>
<!--表示软提交达到1万条的时候会自动进行一次硬提交-->
<maxDocs>10000</maxDocs>

<!--表示软提交10秒之后会执行一次硬提交-->
<maxTime>10000</maxTime>

<!--true表示每一次硬提交都开启一个新的Searcher-->
<openSearcher>false</openSearcher>
</autoCommit>

2.软提交是提交数据到内存里面,并没有持久化到磁盘,但是他会把提交的记录写到tlog的日志文件里面所以如果jvm崩溃,那这部分索引就没了

下面就是自动软提交的配置,不需要自己维护提交(默认没有开启):

1
2
3
4
<autoSoftCommit> 
<!--5秒执行一次软提交-->
<maxTime>5000</maxTime>
</autoSoftCommit>

solr 单节点安装

下面说说我的solr学习笔记之 solr6.5.0 + jetty + mysql 使用 DIH 搭建 solr 服务

参考:https://wiki.apache.org/solr/DIHQuickStart

首先下载solr,下载地址为:http://lucene.apache.org/solr/

截至写该笔记时,solr的版本为6.5.0,下载solr-6.5.0.tgz后,将其解压到任意一个目录。当然,目录路径不要有中文。

1
2
# cd /home/hewentian/ProjectD
$ tar xzvf solr-6.5.0.tgz

我解压到/home/hewentian/ProjectD/solr-6.5.0,目录结构如下:
bin
contrib
dist
docs
example
licenses
server
CHANGES.txt
LICENSE.txt
LUCENE_CHANGES.txt
NOTICE.txt
README.txt

solr的软件包,默认使用jetty部署,SOLR6要求JDK8,启动solr的命令很简单:
在DOS窗口中命令如下:

1
$ /home/hewentian/ProjectD/solr-6.5.0/bin/solr start

然后在浏览器中可以访问:
http://localhost:8983/solr

在server/solr目录下,有一个README.txt的文件,其中说明了如何建立solr core。
最简单的建立是直接复制solr中为我们提供好的例子,打开server/solr/configsets目录会发现里面已经有三个例子,如下:
basic_configs
data_driven_schema_configs
sample_techproducts_configs

因为我们是要从数据库导入数据,所以选择以 “data_driven_schema_configs” 这个例子为模板创建我们的core: mysqlCore。
在DOS窗口中命令如下:

1
$ /home/hewentian/ProjectD/solr-6.5.0/bin/solr create -c mysqlCore -d data_driven_schema_configs

说明:
-c: 指定创建的core为mysqlCore
-d:指定以data_driven_schema_configs为模板

执行上面的命令后在/home/hewentian/ProjectD/solr-6.5.0/server/solr目录下会有一个文件夹mysqlCore

然后在浏览器中可以访问:
http://localhost:8983/solr

你会在[Core Selector]中看到mysqlCore,但是目前还不能使用DIH导入数据,需下面的设置。

建数据表,并插入3条记录,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
CREATE DATABASE /*!32312 IF NOT EXISTS*/`test` /*!40100 DEFAULT CHARACTER SET utf8 */;

USE `test`;

/*Table structure for table `user` */

DROP TABLE IF EXISTS `user`;

CREATE TABLE `user` (
`id` varchar(255) NOT NULL COMMENT '用户id',
`name_` varchar(255) DEFAULT NULL COMMENT '名字',
`age_` int(11) DEFAULT NULL COMMENT '年龄',
`ability_` varchar(100) DEFAULT NULL COMMENT '资格;等级',
`address_` varchar(255) DEFAULT NULL COMMENT '详细地址',
`school1_` varchar(255) DEFAULT NULL COMMENT '学校1',
`school2_` varchar(255) DEFAULT NULL COMMENT '学校2',
`school3_` varchar(255) DEFAULT NULL COMMENT '学校3',
`update_time_` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='用户表';

/*Data for the table `user` */

insert into `user`(`id`,`name_`,`age_`,`ability_`,`address_`,`school1_`,`school2_`,`school3_`,`update_time_`)
values
('1','张三',20,'初级工程师','广东',NULL,NULL,NULL,'2017-10-28 11:39:52'),
('2','李四',20,'中级工程师','湖南','湖南实验小学',NULL,'湖南大学','2017-10-28 11:39:51'),
('3','王五',40,'高级工程师','北京','北京实验小学','北京第一中学','北京大学','2017-10-28 11:39:53');

为了使用mysql导入数据,我们还需要导入两个重要的jar包。由于mysql的jar包并没有在项目中,于是我复制了一份
放到了server/lib/ext目录下面了。我加的是mysql-connector-java-5.1.25.jar,如果你的是另外的版本,要修改下
面的lib中正则的部分。另外两个需要的jar包就是dist目录下带有“dataimport”标识的jar包。
然后打开mysqlCore/conf/solrconfig.xml,引用上面提到的jar包,如下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<lib dir="${solr.install.dir:../../../..}/contrib/extraction/lib" regex=".*\.jar" />
<lib dir="${solr.install.dir:../../../..}/dist/" regex="solr-cell-\d.*\.jar" />

<lib dir="${solr.install.dir:../../../..}/contrib/clustering/lib/" regex=".*\.jar" />
<lib dir="${solr.install.dir:../../../..}/dist/" regex="solr-clustering-\d.*\.jar" />

<lib dir="${solr.install.dir:../../../..}/contrib/langid/lib/" regex=".*\.jar" />
<lib dir="${solr.install.dir:../../../..}/dist/" regex="solr-langid-\d.*\.jar" />

<lib dir="${solr.install.dir:../../../..}/contrib/velocity/lib" regex=".*\.jar" />
<lib dir="${solr.install.dir:../../../..}/dist/" regex="solr-velocity-\d.*\.jar" />

<!-- 上面的lib为原本有的,下面的lib为添加的 -->
<lib dir="${solr.install.dir:../../../..}/dist/" regex="solr-dataimporthandler-.*\.jar" />
<lib dir="${solr.install.dir:../../../..}/server/lib/ext/" regex="mysql-connector-java-5.1.25.jar" />

添加requestHandler
在mysqlCore/conf/solrconfig.xml,搜索<requestHandler name="/select" class="solr.SearchHandler">
然后在该行之上添加如下代码。

1
2
3
4
5
<requestHandler name="/dataimport" class="solr.DataImportHandler">
<lst name="defaults">
<str name="config">db-data-config.xml</str>
</lst>
</requestHandler>

在mysqlCore/conf目录下新建db-data-config.xml, 内容如下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<dataConfig>
<dataSource name="ds" type="JdbcDataSource" driver="com.mysql.jdbc.Driver"
url="jdbc:mysql://localhost:3306/test" user="root" password="root" />
<document>
<entity name="user" pk="id" dataSource="ds" query="select * from user"
deltaQuery="select id from user where update_time_>'${dataimporter.last_index_time}'"
deltaImportQuery="select t.* from user t where t.id='${dataimporter.delta.id}'">
<field name="id" column="id" />
<field name="name" column="name_" />
<field name="age" column="age_" />
<field name="ability" column="ability_" />
<field name="address" column="address_" />

<!-- 将DB中的多个列,在solr中以数组形式存储到一个field中 -->
<field name="schools" column="school1_" />
<field name="schools" column="school2_" />
<field name="schools" column="school3_" />

<field name="update_time" column="update_time_" />
</entity>
</document>
</dataConfig>

说明:
dataSource是数据库数据源。Entity就是一张表对应的实体,pk是主键,query是查询语句。
Field对应一个字段,column是数据库里的column名,后面的name属性对应着Solr的Filed的名字。
其中test是数据库名,user是表名。

在mysqlCore/conf/managed-schema配置field信息,其中id的field本身已有。默认的 filed 不要删。

1
2
3
4
5
6
7
<field name="id" type="string" indexed="true" stored="true" required="true" multiValued="false" />
<field name="name" type="string" indexed="true" stored="true"/>
<field name="age" type="int" indexed="true" stored="true"/>
<field name="ability" type="string" indexed="true" stored="true"/>
<field name="address" type="string" indexed="true" stored="true"/>
<field name="schools" type="text_general" multiValued="true" indexed="true" stored="true"/>
<field name="update_time" type="date" multiValued="false" indexed="true" stored="true"/>

由于修改了配置文件,所以要重启solr,命令如下:

1
2
$ /home/hewentian/ProjectD/solr-6.5.0/bin/solr stop -all
$ /home/hewentian/ProjectD/solr-6.5.0/bin/solr start

然后在浏览器中可以访问:
http://localhost:8983/solr

点击[Core Selector]->mysqlCore->Dataimport在新的页面中按如下选择:
Command: full-import
Entity:user
Auto-Refresh Status
然后点[Execute]

成功后,点[Query]即可查询。

git 学习笔记

设置用户名和邮箱

全局设置方式:

1
2
$ git config --global user.name "hewentian"
$ git config --global user.email "wentian.he@qq.com"

单独对某个仓库设置方式:

1
2
$ git config user.name "hewentian"
$ git config user.email "wentian.he@qq.com"

可以通过如下方式查看设置结果:

1
2
$ git config user.name
$ git config user.email

创建SSH KEY

1
$ ssh-keygen -t rsa -C "youremail@example.com"

下面记录一些经常会用到的命令:

查看远程分支, 加上 -a 参数可以查看远程分支,远程分支会用红色表示出来(如果你开了颜色支持的话),不加 -a 则查看本地分支:

1
2
3
4
5
6
$ git branch -a
dev
* master
remotes/origin/HEAD -> origin/master
remotes/origin/master
remotes/origin/prod

删除远程分支和tag, 在Git v1.7.0 之后,可以使用这种语法删除远程分支:

1
$ git push origin --delete <branchName>

删除tag这么用:

1
$ git push origin --delete tag <tagname>

否则,可以使用这种语法,推送一个空分支到远程分支,其实就相当于删除远程分支:

1
$ git push origin :<branchName>

这是删除tag的方法,推送一个空tag到远程tag:

1
2
$ git tag -d <tagname>
$ git push origin :refs/tags/<tagname>

两种语法作用完全相同。

将远程git仓库里的指定分支拉取到本地(本地不存在的分支)
当我想从远程仓库里拉取一条本地不存在的分支时:

1
$ git checkout -b 本地分支名 origin/远程分支名

这个将会自动创建一个新的本地分支,并与指定的远程分支关联起来。

例如远程仓库里有个分支dev2,我本地没有该分支,我要把dev2拉到我本地:

1
$ git checkout -b dev2 origin/dev2

若成功,将会在本地创建新分支dev2,并自动切到dev2上。
如果出现提示:

fatal: Cannot update paths and switch to branch 'dev2' at the same time.
Did you intend to checkout 'origin/dev2' which can not be resolved as commit?

表示拉取不成功。我们需要先执行

1
$ git fetch

然后再执行下面的命令即可

1
$ git checkout -b 本地分支名 origin/远程分支名

Git 比较不同版本文件差异的常用命令格式:

1
2
3
4
5
6
7
$ git diff	查看尚未暂存的文件中更新了哪些部分
$ git diff filename 查看尚未暂存的某个文件更新了哪些部分
$ git diff –-cached 查看已经暂存起来的文件中和上次提交的版本之间的差异
$ git diff –-cached filename 查看已经暂存起来的某个文件和上次提交的版本之间的差异
$ git diff <commitId1> <commitId2> 查看某两个版本之间的差异
$ git diff <commitId1>:filename <commitId2>:filename 查看某两个版本的某个文件之间的差异,方式一
$ git diff <commitId1> <commitId2> -- filename 查看某两个版本的某个文件之间的差异,方式二

在git中查看历史的命令主要是git log,要查看某个文件的修改历史:

1
$ git log -- begin.txt

可以添加不同的选项让输出的内容或格式有所不同。

1
$ git log -p -- begin.txt

-p 选项可以输出每次提交中的diff, -p会把输出搞得很长、很乱,不容易找到重点。
还有另外一种方式是:

1
$ git log --pretty=oneline -- filename

在log 命令中加入 –pretty=oneline 选项只能看到comments,看不到提交的用户和日期。
这也能够让我们集中注意力快速找到关注的提交记录。

然后使用 git show命令查看完整的提交内容。

当然,除了命令行工具您也可以使用GUI程序查看文件的历史记录:
gitk filename

查看历史中的文件内容

当我们使用 git log 命令找到了某次提交,并且想看看这次提交时文件的完整内容。
这时,我们需要使用 git show 命令:

1
$ git show <commitId>:filename

也许此时你并不是看看就算了,你想要使用这个版本的文件更新工作区中的文件。
直接从 git show 命令的输出中拷贝内容是个不错的选择。
但也可以通过组合使用不同的命令来实现:

1
2
$ git checkout <commitId> --filename
$ git reset filename

此时只有工作区被更新了(你也可以把他当做是一次回滚操作)。

git 将单个文件恢复到历史版本的正确方法如下:

1
2
3
$ git log 要恢复的文件路径
$ git reset commit_id 要恢复的文件路径
$ git checkout -- 要恢复的文件路径

git的.gitignore规则不生效的解决办法

有时候定义了规则后发现并未生效,原因是.gitignore只能忽略那些原来没有被track的文件,如果某些文件已经被纳入了版本管理中,则修改.gitignore是无效的。那么解决方法就是先把本地缓存删除(改变成未track状态),然后再提交:

1
2
3
$ git rm -r --cached .
$ git add .
$ git commit -m 'update .gitignore'

在开发的过程中,想知道远程的仓库是否有同事提交代码可以使用如下命令

1
2
3
$ cd {your_repo_dir}
$ git fetch
$ git status

git远程删除分支后,本地 git branch -a 依然能看到的解决办法

远程删掉 release/1.1 分支后,本地使用如下命令依然还能看到它,如下:

1
2
3
4
5
6
7
8
9
10
$ git fetch
$ git branch -a
develop
* developLocal
master
remotes/origin/HEAD -> origin/master
remotes/origin/develop
remotes/origin/feature/develop_1.1
remotes/origin/master
remotes/origin/release/1.1 # 看,它还在

此时我们使用如下命令,可以查看remote地址,远程分支,还有本地分支与之相对应关系等信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
$ git remote show origin 
* remote origin
Fetch URL: ssh://git@gitlab.hewentian.com:12022/hexo.git
Push URL: ssh://git@gitlab.hewentian.com:12022/hexo.git
HEAD branch: master
Remote branches:
develop tracked
feature/develop_1.1 tracked
master tracked
refs/remotes/origin/release/1.1 stale (use 'git remote prune' to remove) # 提示该分支已经不存在了
Local branches configured for 'git pull':
develop merges with remote develop
master merges with remote master
Local refs configured for 'git push':
develop pushes to develop (up to date)
master pushes to master (local out of date)

根据提示,使用如下命令,删掉本地的远程不存在的分支

1
2
3
4
$ git remote prune origin 
Pruning origin
URL: ssh://git@gitlab.hewentian.com:12022/hexo.git
* [pruned] origin/release/1.1

这样就删除了那些远程仓库不存在的分支

git status 显示中文和解决中文乱码

在默认设置下,中文文件名在工作区状态输出,中文名不能正确显示,而是显示为八进制的字符编码。
解决方案,在bash提示符下输入:

1
$ git config --global core.quotepath false

core.quotepath设为false的话,就不会对0x80以上的字符进行quote,中文显示正常。

修复生产问题的方法

在某些情况下,本地可能提交了很多次代码,但此时发现生产有个严重BUG需马上修复,但本地的代码还不能推到生产。此时的解决方法是:

  1. 先找到生产上面最新的commit id,然后在本地以此commit id创建一个新分支;
  2. 在新分支修复,然后将此分支推到生产;
  3. 在生产构建该分支。

相关操作如下:

1
2
3
4
5
6
$ git pull origin master
$ git log
$ git checkout -b fix20191106 03b361719f93a74bb5a5cdc22fd4f621adc2822a
$ git add {修改过的文件}
$ git commit -m "修改原因说明"
$ git push origin fix20191106

将本地仓库提交到多个远程仓库

一般情况下,在本地有一个gitLab,在生产也有一个gitLab。我们要将本地代码提交到生产的gitLab,方法如下:
将本地仓库和生产的远程仓库绑定:

cd ~/ProjectD/gitHub/bigdata
git remote add prod git@github.com:hewentian/bigdata.git

在本地切换到和生产仓库一样的分支,然后提交到生产:

git checkout develop
git push prod develop

git本地分支和远程分支建立追踪关系的三种方式

  1. 手动建立追踪关系

    $ git branch --set-upstream-to=<远程主机名>/<远程分支名> <本地分支名>
    
  2. push时建立追踪关系

    $ git push -u <远程主机名> <本地分支名>
    

加上-u参数,这样push时,本地指定分支就和远程主机的同名分支建立追踪关系。

  1. 新建分支时建立跟踪关系
    $ git checkout -b <本地分支名> <远程主机名>/<远程分支名>
    

markdown 学习笔记

今天开始学习下 markdown 这种标记语言,我习惯了学习一门语言,会去看它的官方文档里面的语法说明,markdown 作者的官方网站:

https://daringfireball.net/projects/markdown/syntax

极力推荐大家去看下。方便自己以后查看,摘录如下:

在 markdown 中插入 <br />,只需在行尾添加 2 个空格,然后回车,即可

要使 markdown 中的 #, >等,显示原义,只要在它们前置 4 个空格即可

1. 标题

标题有1-6级,使用下面这种方式产生:

# This is an H1
## This is an H2
###### This is an H6

Example as below:

This is an H1

This is an H2

This is an H6

2. blockquote

blockquote 以 > 开头,一段当中每一行的开头都加上,你也可以偷懒,只在段落的第一行加上,并且它可以 nested 其他 markdown 标记,

> This is a blockquote with two paragraphs. Lorem ipsum dolor sit amet,
> consectetuer adipiscing elit. Aliquam hendrerit mi posuere lectus.
> Vestibulum enim wisi, viverra nec, fringilla in, laoreet vitae, risus.
> 
> Donec sit amet nisl. Aliquam semper ipsum sit amet velit. Suspendisse
> id sem consectetuer libero luctus adipiscing.

Example as below:

This is a blockquote with two paragraphs. Lorem ipsum dolor sit amet,
consectetuer adipiscing elit. Aliquam hendrerit mi posuere lectus.
Vestibulum enim wisi, viverra nec, fringilla in, laoreet vitae, risus.

Donec sit amet nisl. Aliquam semper ipsum sit amet velit. Suspendisse
id sem consectetuer libero luctus adipiscing.

blockquote 还可以 nested 其他 blockquote

> This is the first level of quoting.
>
> > This is nested blockquote.
>
> Back to the first level.

Example as below:

This is the first level of quoting.

This is nested blockquote.

Back to the first level.


3. List

列表分为有序和无序

3.1 无序列表写法如下:

* Red
* Green
* Blue

Example as below:

  • Red
  • Green
  • Blue

3.2 有序列表写法如下:

1. Red
2. Green
3. Blue

Example as below:

  1. Red
  2. Green
  3. Blue

其中的序号,不影响它的效果,你也可以像下面这样写,它的效果是一样的。

1. Red
1. Green
1. Blue
或
1. Red
6. Green
8. Blue

List items may consist of multiple paragraphs. Each subsequent paragraph in a list item must be indented by either 4 spaces or one tab:

1.  This is a list item with two paragraphs. Lorem ipsum dolor
    sit amet, consectetuer adipiscing elit. Aliquam hendrerit
    mi posuere lectus.

    Vestibulum enim wisi, viverra nec, fringilla in, laoreet
    vitae, risus. Donec sit amet nisl. Aliquam semper ipsum
    sit amet velit.

2.  Suspendisse id sem consectetuer libero luctus adipiscing.

Example as below:

  1. This is a list item with two paragraphs. Lorem ipsum dolor
    sit amet, consectetuer adipiscing elit. Aliquam hendrerit
    mi posuere lectus.

    Vestibulum enim wisi, viverra nec, fringilla in, laoreet
    vitae, risus. Donec sit amet nisl. Aliquam semper ipsum
    sit amet velit.

  2. Suspendisse id sem consectetuer libero luctus adipiscing.

To put a code block within a list item, the code block needs
to be indented twice – 8 spaces or two tabs:

* A list item with a code block:
        <code goes here>

Example as below:

  • A list item with a code block:
    printf("hello world")
    

4. CODE BLOCKS

To produce a code block in Markdown, simply indent every line of the block by at least 4 spaces or 1 tab. For example, given this input:

This is a normal paragraph:
    This is a code block.

Example as below:
This is a normal paragraph:

This is a code block.

5. HORIZONTAL RULES

产生水平分割线的方法有以下几种,它们的效果都是一样的

* * * 
***
******
- - -
------

This is [an example](http://example.com/ "Title") inline link.

[This link](http://example.net/) has no title attribute.

Example as below:
This is an example inline link.

This link has no title attribute.

If you’re referring to a local resource on the same server, you can use relative paths:

See my [About](/about/) page for details.

Example as below:
See my About page for details.

你还可以这样写 links
Reference-style links use a second set of square brackets, inside which you place a label of your choosing to identify the link:

This is [an example][id] reference-style link.

Then, anywhere in the document, you define your link label like this, on a line by itself:

[id]: http://example.com/  "Optional Title Here"

Example as below:
This is an example reference-style link.

Link definition names may consist of letters, numbers, spaces, and punctuation — but they are not case sensitive. E.g. these two links:

[link text][a]
[link text][A]

are equivalent.

The implicit link name shortcut allows you to omit the name of the link, in which case the link text itself is used as the name. Just use an empty set of square brackets — e.g., to link the word “Google” to the google.com web site, you could simply write:

[Google][]

And then define the link:

[Google]: http://google.com/

Example as below:
In china, you can’t use Google, hahaha…


7. EMPHASIS

Markdown treats asterisks (*) and underscores (_) as indicators of emphasis. Text wrapped with one * or _ will be wrapped with an HTML<em>tag; double *’s or _’s will be wrapped with an HTML<strong>tag. E.g., this input:

*single asterisks*
_single underscores_
**double asterisks**
__double underscores__

will produce:

<em>single asterisks</em>
<em>single underscores</em>
<strong>double asterisks</strong>
<strong>double underscores</strong>

Example as below:
single asterisks
single underscores
double asterisks
double underscores

To produce a literal asterisk or underscore at a position where it would otherwise be used as an emphasis delimiter, you can backslash escape it:

\*this text is surrounded by literal asterisks\*

8. CODE

To indicate a span of code, wrap it with backtick quotes (`). Unlike a pre-formatted code block, a code span indicates code within a normal paragraph. For example:

Use the `printf()` function.

will produce:

<p>Use the <code>printf()</code> function.</p>

Example as below:
Use the printf() function.

To include a literal backtick character within a code span, you can use multiple backticks as the opening and closing delimiters:

``There is a literal backtick (`) here.``

which will produce this:

<p><code>There is a literal backtick (`) here.</code></p>

Example as below:
There is a literal backtick (`) here.

Other code format:

` `` java
    public static void main(String[] args) {
        System.out.println("hello world.");
    }
    注意:请将这里的`之间的空格去掉
` ``

Example as below:

1
2
3
public static void main(String[] args) {
System.out.println("hello world.");
}


9. IMAGES

Inline image syntax looks like this:

![Alt text](/path/to/img.jpg)
![Alt text](/path/to/img.jpg "Optional title")

Example as below:
Alt text

Reference-style image syntax looks like this:

![Alt text][id]

Where “id” is the name of a defined image reference. Image references are defined using syntax identical to link references:

[id]: url/to/image  "Optional title attribute"

10. MISCELLANEOUS

AUTOMATIC LINKS

Markdown supports a shortcut style for creating “automatic” links for URLs and email addresses: simply surround the URL or email address with angle brackets. What this means is that if you want to show the actual text of a URL or email address, and also have it be a clickable link, you can do this:

<http://example.com/>

Markdown will turn this into:

<a href="http://example.com/">http://example.com/</a>

BACKSLASH ESCAPES

Markdown allows you to use backslash escapes to generate literal characters which would otherwise have special meaning in Markdown’s formatting syntax. For example, if you wanted to surround a word with literal asterisks (instead of an HTML tag), you can use backslashes before the asterisks, like this:

\*literal asterisks\*

Markdown provides backslash escapes for the following characters:

\   backslash
`   backtick
*   asterisk
_   underscore
{}  curly braces
[]  square brackets
()  parentheses
#   hash mark
+   plus sign
-   minus sign (hyphen)
.   dot
!   exclamation mark

创建表格语法如下:

| Tables        | Are           | Cool  |
| ------------- |:-------------:| -----:|
| col 3 is      | right-aligned | $1600 |
| col 2 is      | centered      |   $12 |
| zebra stripes | are neat      |    $1 |

Markdown 生成表格时,可以给一整列的单元格设置同样的对齐样式

| 第一列   | 第二列   | 第三列  |
| ------:  | :------: | :------ |
| 右对齐   | 居中     | 左对齐  |

markdown 中特殊字符的显示方式:

原样显示 书写方式
| &#124;
< &lt;
&le;
> &gt;
&ge;
# \#
* \*
216 2<sup>16</sup>

end.

Linux 学习笔记

在安装ubuntu的过程中的分区顺序: EFI -> /boot -> swap -> /:

EFI     primary     200M
/boot   primary     512M
swap    logic       内存2倍
/       primary     剩下的容量

例如在小米笔记本安装 ubuntu 18.04 的时候,必须关闭安全启动,secure BOOT,
重启电脑,出现mi时,F2进入BIOS中,在secure中关闭安全启动,对了,要首先设置superviser password, 否则secure boot 无法关闭。

Ubuntu安装ssh时出现软件包 openssh-server 还没有可供安装的候选者错误

错误如下:

sudo apt-get install opensshserver正在读取软件包列表…

完成正在分析软件包的依赖关系树正在读取状态信息…

完成现在没有可用的软件包 openssh-server,

但是他被其他的软件包引用了这可能意味着这个缺失的软件包可能已被废弃,或者只能在其他发布源中找到

Error:软件包 openssh-server 还没有可供安装的候选者

解决方案:分析原因是我们的apt-get没有更新,当然如果你的是最新的系统不用更新也行,但是我相信很多人都是需要更新的吧,操作命令如下:

1
$ sudo apt-get update

更新完毕后执行:

1
2
$ sudo apt-get install openssh-client
$ sudo apt-get install openssh-server

安装完毕之后,启动SSH

1
$ sudo service ssh start

最后我们用命令ps -ef | grep ssh来看下open-server安装成功没有,如果出现像下面的输出,说明安装成功了。

1
2
3
4
$ ps -ef | grep ssh

hewenti+ 2654 2565 0 10:04 ? 00:00:00 /usr/bin/ssh-agent /usr/bin/im-launch env GNOME_SHELL_SESSION_MODE=ubuntu gnome-session --session=ubuntu
hewenti+ 8845 6801 0 10:29 pts/1 00:00:00 grep --color=auto ssh

这样就可以在其他机器连到这台机器或者执行scp命令了。

在ubuntu中的vi编辑器怎么使用
默认情况下ubuntu上也安装有vi但是奇怪的是这个vi是vim-common版本,基本上用不了所以要先把这个版本的vi卸载掉,然后重新安装vim。

1
2
$ sudo apt-get remove vim-common
$ sudo apt-get install vim

useradd与adduser区别

1
2
3
$ adduser username	# 会在/home下建立一个文件夹username
$ useradd username # 不会在/home下建立一个文件夹username
$ useradd -m username # 跟adduser一样,会在/home下建立一个文件夹username

userdel删除用户账号

userdel 会查询系统账户文件,例如/etc/password/etc/group,它会删除所有和用户名相关的文件

1
2
$ userdel peter     # 不带选项使用 userdel,只会删除用户。用户的目录将仍会在/home目录下
$ userdel -r peter # 使用 -r 选项,在删除用户时将完全删除用户的目录、用户的邮件池

还有的就是文件编码的问题,在windows下默认都是用ANSI格式编码,但是在ubuntu下面可能会是其他格式的编码,如果两个系统的编码不一致,就会产生乱码。
最好是都采用UTF-8格式编码

ubuntu root默认密码(初始密码)
ubuntu安装好后,root初始密码(默认密码)是没有的,需要设置。

1、先用安装时候的用户登录进入系统

2、输入:

1
sudo passwd

按回车

3、输入新密码,重复输入密码,最后提示passwd:password updated sucessfully

此时已完成root密码的设置

4、输入:

1
$ su root

切换用户到root试试…….

如果执行./configure无法执行,
要安装:

1
$ sudo apt-get install build-essential

在ubuntu软件源里zlib和zlib-devel叫做zlib1g、zlib1g.dev

1
2
$ sudo apt-get install zlib1g
$ sudo apt-get install zlib1g.dev

直接输入上述命令后还是不能安装。这就要求我们先装ruby,默认的安装源里没有zlib1g.dev。要在packages.ubuntu.com上找。

1
$ sudo apt-get install ruby

然后再装zlib1g-dev就可以了

1
$ sudo apt-get install zlib1g-dev

解决依赖包openssl安装,命令:
[cpp] view plain copy 在CODE上查看代码片派生到我的代码片

1
$ sudo apt-get install openssl libssl-dev

解决依赖包pcre安装,命令:
[cpp] view plain copy 在CODE上查看代码片派生到我的代码片

1
$ sudo apt-get install libpcre3 libpcre3-dev

解决依赖包zlib安装,命令:
[cpp] view plain copy 在CODE上查看代码片派生到我的代码片

1
$ sudo apt-get install zlib1g-dev

当你安装完ubuntu后,安装五笔输入法:

1.打开命令行输入:

1
$ sudo apt-get install fcitx-table-wubi

安装完后,重启(也可以在下面的设置完毕之后,再重启)

2.System Settings -> language support 在 Keyboard input method system 中选中 fcitx
然后点击 Apply System-Wide, 然后重启

3.重启后,System Settings -> Text Entry, 中输入 Wubi(Fcitx),这样,就完成了五笔输入法的安装。

ubuntu 安装 Robo3t 出现 Available platform plugins are: xcb.

解决办法,打开终端输入一下命令

1
2
$ mkdir ~/robo-backup
$ mv robo3t-1.1.1-linux-x86_64-c93c6b0/lib/libstdc++* ~/robo-backup/

输入命令之后会在robo-backup中出现两个文件 libstdc++.so.6 和 libstdc++.so.6.0.22,然后启动robo3t就ok了

其实,也可以將其删掉,只要你还有压缩包,即可。

ubuntu 下 Eclipse 中 syso 快捷键 Alt + / 不能使用的问题

window -> Preferences -> general -> keys中,
找到 content asist 修改下边值
Binding 改成 Alt+/ 输入的时候要注意,长按Alt键,然后按下/键即可
When 改为 Editing Text
ok.

ubuntu 使用switchHosts修改host后启动eclipse项目报错

1
2
3
4
错误: 抛出异常错误: `java.net.MalformedURLException: Local host name unknown: java.net.UnknownHostException:
localhost: hewentian-Lenovo-IdeaPad-Y470`: 未知的名称或服务
Error: Exception thrown by the agent : java.net.MalformedURLException: Local host name unknown:
java.net.UnknownHostException: localhost: hewentian-Lenovo-IdeaPad-Y470: Name or service not known

原因是/etc/hosts文件里没有主机名为:hewentian-Lenovo-IdeaPad-Y470,解决方法就是在switchHosts中增加如下代码:

1
2
127.0.0.1  hewentian-Lenovo-IdeaPad-Y470
localhost hewentian-Lenovo-IdeaPad-Y470

Linux查看程序端口占用情况

1
2
3
4
5
6
7
8
9
10
11
$ netstat -apn | grep 8761
(Not all processes could be identified, non-owned process info
will not be shown, you would have to be root to see it all.)
tcp6 0 0 :::8761 :::* LISTEN 24831/java
tcp6 0 0 127.0.0.1:49958 127.0.0.1:8761 ESTABLISHED 24824/java
tcp6 0 0 127.0.0.1:50494 127.0.0.1:8761 TIME_WAIT -
tcp6 0 0 127.0.0.1:50502 127.0.0.1:8761 TIME_WAIT -
tcp6 0 0 127.0.0.1:50484 127.0.0.1:8761 TIME_WAIT -
tcp6 0 0 127.0.0.1:8761 127.0.0.1:49958 ESTABLISHED 24831/java
unix 3 [ ] STREAM CONNECTED 2887618 21883/chrome
unix 3 [ ] STREAM CONNECTED 2887619 22047/chrome --type

其中最后一栏是PID/Program name

其他使用方法

1
2
3
4
netstat -ntlp    // 查看当前所有tcp端口
netstat -ntulp | grep 9012 // 查看所有9012端口使用情况

lsof -i:8020 // 查看8020端口是否开启

检查远程端口是否可以连通

方法一:使用telnet

telnet localhost <port>    // On the server, try to see if the port is open there
telnet <server> <port>     // On the client, try to see if the port is accessible remotely

示例:

1
2
3
4
5
$ telnet 192.168.8.112 8088

Trying 192.168.8.112...
Connected to 192.168.8.112.
Escape character is '^]'.

方法二:使用nc

1
2
$ nc -v 192.168.8.112 8088
Connection to 192.168.8.112 8088 port [tcp/omniorb] succeeded!

redHat安装nc

sudo yum install -y nc

ubuntu下安装notepadqq

安装过程中参考了如下文章:
https://www.linuxtechi.com/notepadqq-notepad-for-ubuntu-linux/

Step:1 Add Ubuntu PPA Repository

‘notpadqq‘ package is not available in the default Ubuntu repository, we will add Ubuntu PPA repository using below command.

1
$ sudo add-apt-repository ppa:notepadqq-team/notepadqq

Step:2 Refresh the Repositories using below apt-get command.

1
$ sudo apt-get update

Step:3 Install notepaddqq Debian package

1
$ sudo apt-get install notepadqq

成功。

ubuntu安装mysql 8 client

1
2
3
4
$ wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.11-1_all.deb
$ sudo dpkg -i mysql-apt-config_0.8.11-1_all.deb
$ sudo apt-get update
$ sudo apt-get install mysql-client

ubuntu Navicat for MySQL 安装以及破解方案

首先上官网上下载LINUX版本: http://www.navicat.com/download/navicat-for-mysql

  1. 下载 navicat120_mysql_en_x64.tar.gz 文件

  2. 下载后解压tar文件

    1
    tar -xzvf /home/hewentian/Downloads/navicat120_mysql_en_x64.tar.gz
  3. 解压后 进入解压后的目录运行命令:

    1
    ./start_navicat

这样OK啦

连接上数据库后里面的中文数据是乱码,把Ubuntu的字符集修改为zh_CN.utf8就行了,修改方法:

  1. 查看当前系统的字符集:echo $LANG
  2. 查看系统支持的字符集: locale -a
  3. 修改字符集: export LANG=zh_CN.utf8
  4. 打开start_navicat文件,会看到 export LANG=”en_US.UTF-8” 将这句话改为 export LANG=”zh_CN.UTF-8”

经过以上修改,我的还是有中文乱码。

破解试用期方案:
第一次执行start_navicat时,会在用户主目录下生成一个名为.navicat64的隐藏文件夹,只要重新删除该文件即可重新计算14天试用期。

1
2
3
4
$ cd /home/hewentian
$ ls -a # 显示隐藏文件内的所有文件
$ rm -rf .navicat64 # 删除该文件
$ # 或者删除此目录下的system.reg文件,但是没有效果

把文件夹删除后,下次启动navicat会重新生成此文件,14天试用期会按新的时间开始计算。

注意:现在已经用DBeaver来代替Navicat了。我目前使用的是dbeaver-ce-7.3.1-linux.gtk.x86_64.tar.gz,它支持Mysql 8,解压后,就可以直接使用啦。

linux中解压rar文件

可以先执行如下命令,看系统是否已经安装rar命令

1
2
3
4
$ rar

The program 'rar' is currently not installed. You can install it by typing:
sudo apt install rar

如果输出如上面,则Linux中未安装rar命令,按提示安装即可

1
2
3
4
5
6
7
8
9
10
$ sudo apt install rar
[sudo] password for hewentian:
Reading package lists... Done
Building dependency tree
Reading state information... Done
Suggested packages:
unrar
The following NEW packages will be installed:
rar
0 upgraded, 1 newly installed, 0 to remove and 142 no

等待安装完成即可,验证是否成功安装,输入rar即可,看到如下输出,即证明安装成功。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$ rar

RAR 5.30 beta 2 Copyright (c) 1993-2015 Alexander Roshal 4 Aug 2015
Trial version Type RAR -? for help

Usage: rar <command> -<switch 1> -<switch N> <archive> <files...>
<@listfiles...> <path_to_extract\>

<Commands>
a Add files to archive
c Add archive comment
ch Change archive parameters
cw Write archive comment to file
d Delete files from archive

解压方法很简单:

1
$ rar x 要解压的文件名.rar

这将压缩包解压在当前目录下

当安装软件的时候出现如下错误的时候

1
2
linux-image-extra-4.10.0-38-generic depends on linux-image-4.10.0-38-generic; however:
Package linux-image-4.10.0-38-generic is not configured yet.

解决方法如下:

1
$ sudo dpkg --configure -a

在Ubuntu上检查一个软件包是否安装

要检查特定的包,比如firefox是否安装了,使用这个命令:

1
$ dpkg -s firefox

同样,你可以使用dpkg-query 命令。这个命令会有更好的输出,当然,你可以用通配符。

1
$ dpkg-query -l firefox

要列出你系统中安装的所有包,输入下面的命令:

1
$ dpkg --get-selections

你同样可以通过grep来过滤找到更精确的包。比如,我想要使用dpkg命令查看系统中安装的gcc包:

1
$ dpkg --get-selections | grep gcc

如果知道一个命令,比如mysql,要想知道它安装在哪里,使用

1
2
$ whereis mysql
mysql: /usr/bin/mysql /etc/mysql /usr/share/man/man1/mysql.1.gz

然后找到它的安装包

1
2
$ dpkg -S /usr/bin/mysql
mariadb-client-core-10.1: /usr/bin/mysql

然后卸载它

1
$ sudo apt-get remove --purge mariadb-client-core-10.1

ubuntu 解压zip文件出现乱码

由于zip格式中并没有指定编码格式,Windows下生成的zip文件中的编码是GBK/GB2312等,因此,导致这些zip文件在Linux下解压时出现乱码问题,因为Linux下的默认编码是UTF8

有2种方式解决问题:

  1. 通过unzip命令解压,指定字符集

    unzip -O CP936 {要解压的文件名}.zip (用GBK, GB18030也可以)
    unzip -O CP936 {要解压的文件名}.zip -d {目标文件夹名}    # -d 指定解压到这个目录
    
  2. 在环境变量中,指定unzip参数,总是以指定的字符集显示和解压文件

    vi /etc/environment
    
    # 加入下面2行
    UNZIP="-O CP936"
    ZIPINFO="-O CP936"
    

在 Ubuntu 上面远程连回 Windows 7

  1. 首先需要开启 Windows 7 上的远程桌面: 打开[控制面板] -> [管理工具] -> [服务] -> [Terminal Services], 开启该服务(有可能找不到);
  2. 然后右击 [我的电脑] -> 选择[属性] -> 远程设置 -> 远程 -> 选择远程协助中的 [允许远程协助连接这台计算机],下面的远程桌面选择 [允许运行任意版本远程桌面的计算机连接];
  3. 有可能还需要关闭[防火墙];
  4. 在 Ubuntu 上面使用如下命令连回 Windows 7;
    1
    2
    3
    4
    5
    6
    7
    $ rdesktop {Windows7_IP}
    或者
    $ rdesktop {Windows7_IP} -f -u {YOUR_LOGIN_NAME} -p {YOUR_PASSWD}
    # -f 全屏,直接输入用户名和密码, 以全屏方式进入 windows 的退出方式是 [开始] -> [断开连接]

    # 也可以将本地linux上面的一个目录,映射到要远程到的windows机。下面将/home/hewentian/Documents映射到远程windows上面的盘hwt
    $ rdesktop {Windows7_IP} -f -u {YOUR_LOGIN_NAME} -p {YOUR_PASSWD} -r disk:hwt=/home/hewentian/Documents

如果没有执行步骤2,则会报如下错:

1
2
3
Autoselected keyboard map en-us
ERROR: CredSSP: Initialize failed, do you have correct kerberos tgt initialized ?
Failed to connect, CredSSP required by server.

你也可以将这些命令,写成SHELL脚本

1
2
3
$ touch rd.sh
$ chmod +x rd.sh
$ sh rd.sh

并在rd.sh中输入以下内容

1
2
3
4
5
6
7
8
9
10
11
12
#! /bin/sh
echo "starting rdesktop ..."
echo ""
ipAddr=192.168.1.100
user=administrator
passwd=pw12345678
echo "rdesktop to $ipAddr"

rdesktop $ipAddr -u $user -p $passwd -g 1300*800 -r clipboard:PRIMARYCLIPBOARD -r disk:hwt=/home/hewentian/Documents

echo "succeeded..."
sleep 1

Linux下的任务调度分为两类,系统任务调度和用户任务调度。

  1. 系统任务调度:系统周期性所要执行的工作,比如写缓存数据到硬盘、日志清理等。在/etc目录下有一个crontab文件,这个就是系统任务调度的配置文件。
    /etc/crontab文件包括下面几行:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    # /etc/crontab: system-wide crontab
    # Unlike any other crontab you don't have to run the `crontab'
    # command to install the new version when you edit this file
    # and files in /etc/cron.d. These files also have username fields,
    # that none of the other crontabs do.

    SHELL=/bin/sh
    PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin

    # m h dom mon dow user command
    17 * * * * root cd / && run-parts --report /etc/cron.hourly
    25 6 * * * root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.daily )
    47 6 * * 7 root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.weekly )
    52 6 1 * * root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.monthly )
    #
  2. 用户任务调度:用户定期要执行的工作,比如用户数据备份、定时邮件提醒等。用户可以使用 crontab 工具来定制自己的计划任务。所有用户定义的crontab 文件都被保存在 /var/spool/cron目录中。其文件名与用户名一致

查看crontab服务状态:

1
$ /etc/init.d/cron status  # 可用的参数 force-reload | reload | restart | start | status | stop

crontab 的用法

1
2
3
4
5
6
7
usage:	crontab [-u user] file
crontab [ -u user ] [ -i ] { -e | -l | -r }
(default operation is replace, per 1003.2)
-e (edit user's crontab)
-l (list user's crontab)
-r (delete user's crontab)
-i (prompt before deleting user's crontab)

例子如下:

1
$ crontab -e

在打开的文件中输入如下内容,这将会在每分钟往文件中输出时间

1
*/1 * * * * /bin/date >> /home/hewentian/Documents/a.txt

一个crontab备份数据的示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
############################################################
# desc: backup important data. every saturday 23:50 run, and the cron is:
# 50 23 * * 6 /bin/sh /home/hewentian/backupData.sh >> /home/hewentian/backupData.log 2>&1
# author: Tim Ho
# mail: wentian.he@qq.com
# created time: 2019-07-24 10:22:28 AM
############################################################

#!/bin/sh

# create the base backup dir, if not exists
backupBaseDir=/home/hewentian/backupData/
if [ ! -d "$backupBaseDir" ]; then
mkdir -p "$backupBaseDir"
fi

# create current backup dir, if not exists
backupDir=$backupBaseDir`date +%Y%m%d`"/"
if [ ! -d "$backupDir" ]; then
mkdir "$backupDir"
fi

# begin to backup data
echo "-------------------- begin to backup data $(date) --------------------"

echo "start to backup userInfo, about 0.30G"
mongoexport -h 192.168.1.100 --port 27017 -u mongo_account -p mongo_account --authenticationDatabase mongo_account -d mongo_account -c userInfo -o "$backupDir"userInfo.json
echo -e "end to backup userInfo $(date)\n"

echo "start to backup carInfo, about 0.18G"
mongoexport -h 192.168.1.100 --port 27017 -u mongo_account -p mongo_account --authenticationDatabase mongo_account -d mongo_account -c carInfo -o "$backupDir"carInfo.json
echo -e "end to backup carInfo $(date)\n"

# at last, delete the files backup 7 days ago
find "$backupBaseDir" -type d -mtime +7 -exec rm -rf {} \;
#find "$backupBaseDir" -mtime +7 -name '*.json' -exec rm -rf {} \;

echo "-------------------- end to backup data $(date) --------------------"

Ubuntu中访问共享文件夹和FTP

  1. 访问共享文件夹:在资源浏览器[Connect to Server]窗口输入:smb://需要访问的机器IP,等同于Windows下输入:\IP
  2. 访问FTP机器:在资源浏览器[Connect to Server]窗口输入:ftp://192.168.1.128/
  3. [Connect to Server]~/.config/nautilus/servers中,可以编辑它的bookmark

curl模拟http发送get或post请求

参照:http://www.voidcn.com/blog/Vindra/article/p-4917667.html

  1. get请求

    curl "http://www.hewentian.com"     如果这里的URL指向的是一个文件或者一幅图都可以直接下载到本地
    curl -i "http://www.hewentian.com"  显示全部信息
    curl -l "http://www.hewentian.com"  只显示头部信息
    curl -v "http://www.hewentian.com"  显示get请求全过程解析
    wget "http://www.hewentian.com"     也可以
    
  2. post请求

    curl -d "param1=value1&param2=value2" "http://www.hewentian.com"
    
  3. json格式的post请求

    curl -l -H "Content-type: application/json" -X POST -d '{"phone":"13800138000","password":"passwd"}' http://www.hewentian.com/apis/users
    

ubuntu 16.04 安装 google-chrome-stable_current_amd64.deb 方法

1
2
3
4
5
6
7
8
9
10
11
$ cd {google-chome所在目录}
$ sudo dpkg -i google-chrome-stable_current_amd64.deb
$ # 如果安装过程输出如下错误
$ # google-chrome-stable depends on libappindicator1; however:
$ # 那么执行如下命令
$ sudo apt-get -f install libappindicator1 libindicator7
$ # 然后再执行原来的安装命令
$ sudo dpkg -i google-chrome-stable_current_amd64.deb

卸载方法
$ sudo apt-get remove google-chrome-stable

Ubuntu 16.04 关闭笔记本触摸板

  1. 禁用触摸板

    1
    $ sudo rmmod psmouse
  2. 重启触摸板

    1
    $ sudo modprobe psmouse

linux下查看某命令的具体位置使用which,如:

1
$ which ab

在Linux/unix 平台上的sqlplus中,如果输错了字符,要想删除,习惯性的按下backspace键后,发现非但没有删除想要删掉的字符,还多出了两个字符^H。当然,我们可以同时按下ctrl+backspace键来删除,但对于习惯了用backspace来删除的用户,这样很不爽。这可以通过修改tty终端的设置来实现backspace删除功能。通过使用stty命令,就可以查看或者修改终端的按键设置。

例如,设置backspace为删除键:

1
$ stty erase ^h

如果要改回使用ctrl+backspace为删除键

1
$ stty erase ^?

如果需要重启后自动设置终端,可以将上述命令加入到profile中。可以通过stty -a命令来查看所有的终端设置。下面是在linux下执行的输出:

1
2
$ stty -a
$ cat /etc/os-release

关于Linux中的so文件

  1. so文件就是通常说的动态链接库,就跟windows下的dll文件差不多;
  2. ko是内核模块文件,驱动之类的啥的;
  3. 不过在linux系统下文件的后缀多数情况下只是个标识,有可能代表不了文件的真实属性的。

linux下采用LD_PRELOAD机制动态修改方法和注入代码

LD_PRELOAD是Linux下的一个环境变量,动态链接器在载入一个程序所需的所有动态库之前,
首先会载入LD_PRELOAD环境变量所指定的动态库。运用这个机制,我们可以修改/替换已有动态库中的方法,
加入我们自己的逻辑,从而改变程序的执行行为。不过该方法只对动态链接的程序有效,对静态链接的程序无效。

linux查找一个目录的命令

1
查找目录:find /(查找范围) -name '查找关键字' -type d

Linux查找含有某字符串的所有文件

grep -rn "hello,world!" *

* : 表示当前目录所有文件,也可以是某个文件名
-r 是递归查找
-n 是显示行号
-R 查找所有文件包含子目录
-i 忽略大小写
-v, --invert-match        select non-matching lines

还可以使用正则表达式:
grep -E ‘[0-9]+ms’ mongod.log

这个命令查询mongod.log日志中包含毫秒时间ms的所有日志。

如果我想查询helloworld
grep -E ‘hello|world’ mongod.log

linux下面md5sum的使用

1
2
3
4
5
6
7
8
9
10
对一个文件计算MD5值
$ md5sum apache-tomcat-8.0.47.tar.gz
0fd249576c33fa71947bc7d296d5b0a9 apache-tomcat-8.0.47.tar.gz

对一个文件计算MD5值,并保存到文件中
$ md5sum apache-tomcat-8.0.47.tar.gz > apache-tomcat-8.0.47.tar.gz.md5

用MD5文件校验原来的文件是否被修改过
$ md5sum -c apache-tomcat-8.0.47.tar.gz.md5
apache-tomcat-8.0.47.tar.gz: OK

端口的分类:

端口在报头中占两个字节,也就是16位。端口号用来表示和区别网络中的不同应用程序。端口分为三大类:

  1. 公认端口(Well Known Ports):0-1023之间的端口号,在LINUX中这些端口你不能随便使用。这些端口由 IANA 分配管理。IANA 把这些端口分配给最重要的一些应用程序,让所有的用户都知道,当一种新的应用程序出现后,IANA必须为它指派一个公认端口。 常用的公认端口有:

    FTP:    21
    TELNET:    23
    SMTP:    25
    DNS:    53
    TFTP:    69
    HTTP:    80
    SNMP:    161
    
  2. 注册端口(Registered Ports):从1024-49151,是公司和其他用户向互联网名称与数字地址分配机构(ICANN)登记的端口号,利用因特网的传输控制协议(TCP)和用户数据报协议(UDP)进行通信的应用软件需要使用这些端口。在大多数情况下,这些应用软件和普通程序一样可以被非特权用户打开。

  3. 客户端使用的端口号:49152~65535,这类端口号仅在客户进程运行时才动态选择,因此又叫做短暂端口号。被保留给客户端进程选择暂时使用的。也可以理解为,客户端启动的时候操作系统随机分配一个端口用来和服务器通信,客户端进程关闭下次打开时,又重新分配一个新的端口。

端口就像一道门,外部可以通过不同的端口和本机上不同服务的进程进行交流。而IP 地址和端口号标识了接入互联网主机的唯一 一个进程

ubuntu 中使用 SQuirreL 连接各种 RDBMS

参考:http://www.opensoce.com/367.html

使用SQuirreL SQL Client连接各种RDBMS数据库,其官方网站为:http://sourceforge.net/projects/squirrel-sql,
截至写本文时,其最新版本为:squirrel-sql-snapshot-20171121_2249,其最大的魅力在于:

  1. 基于Java,具备良好的夸平台特性,在Windows下一样可以很好的使用;
  2. 只要具备相应数据库的类库,就可以连接对应的数据库,例如SQL Server、MySQL、Oracle、Sybase、DB2等等。

首先下载:
http://sourceforge.net/projects/squirrel-sql

然后确保系统已经安装java,然后切换到squirrel-sql-snapshot-20171121_2249-standard.jar所在目录执行:

1
$ java -jar squirrel-sql-snapshot-20171121_2249-standard.jar

然后根据提示选择安装路径,我安装到/home/hewentian/ProjectD/squirrel-sql-snapshot-20171121_2249,后续安装步骤中,插件我选择了

Data import
DBCopy
DBDiff
Microsoft SQL Server
MySQL
Oracle

安装完成之后,需要去下载相应的RDBMS的jar包:
SQL Server(jtds):
http://sourceforge.net/projects/jtds/files/

mysql(MySQL Connector):
http://dev.mysql.com/downloads/connector/j/

oracle(JDBC):
http://www.oracle.com/technology/global/cn/software/tech/java/sqlj_jdbc/index.html

然后将jtds-1.3.1.jarojdbc14.jarmysql-connector-java-5.1.25.jar复制到SQuirrel SQL安装目录下的lib目录,这样SQuirrel SQL就具备了连接SQL ServerOracleMySQL的能力。

最后,到SQuirreL的目录重启SQuirreL:

1
2
$ cd /home/hewentian/ProjectD/squirrel-sql-snapshot-20171121_2249
$ ./squirrel-sql.sh

之后在左侧Aliases中添加一个Alias,填入正确的连接信息内容类似于:

Name: 输入连接的名字
Driver: jTDS Microsoft SQL
URL: 
User Name: 
Password: 

这样就可以连接了。

修改SSH的默认22端口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
首先查看是否有使用22端口
$ lsof -i:22
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
sshd 934 root 3u IPv4 8688 0t0 TCP *:ssh (LISTEN)
sshd 2305 root 3r IPv4 25836 0t0 TCP 123.57.238.142:ssh->66.133.135.219.broad.gz.gd.dynamic.163data.com.cn:60064 (ESTABLISHED)

查看防火墙的情况,看下是否会允许你要修改的端口通过
$ iptables -nL

$ vim /etc/ssh/sshd_config
找到Port这一行,修改为你想要的端口,这里设置为:12022,前提是该端口还没被其他程序使用

重启SSH
$ /etc/init.d/sshd restart
Stopping sshd: [ OK ]
Starting sshd: [ OK ]

$ lsof -i:12022
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
sshd 2382 root 3u IPv4 28005 0t0 TCP *:12022 (LISTEN)
sshd 2388 root 3r IPv4 28216 0t0 TCP 123.57.238.142:12022->66.133.135.219.broad.gz.gd.dynamic.163data.com.cn:41068 (ESTABLISHED)

可以看到端口已经修改过来了,再使用之前的命令就无法登录了
$ ssh -p 22 root@123.57.238.142
ssh: connect to host 123.57.238.142 port 22: Connection refused

ubuntu 连接到跳板机

先将密钥文件hewentian.pem放到用户SSH目录下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
$ cd ~/.ssh
$ cp ~/Downloads/hewentian.pem ./

修改权限
$ chmod 600 hewentian.pem

创建一个配置文件,如果没有的话
$ touch config

并在其中输入如下内容
Host jump_server
User hewentian
Hostname 192.168.1.100
Port 12022
PreferredAuthentications publickey
IdentityFile ~/.ssh/hewentian.pem

这样,在使命行中输入: ssh jump_server就可以跳到跳板机了

如果你有两台跳板机:开发环境、生产环境,你可以在config文件中同时配置两个:

1
2
3
4
5
6
7
8
9
10
11
12
13
Host jump_dev
User hewentian
Hostname 192.168.1.100
Port 12022
PreferredAuthentications publickey
IdentityFile ~/.ssh/hewentian.pem

Host jump_prod
User hewentian
Hostname 111.112.113.114
Port 12022
PreferredAuthentications publickey
IdentityFile ~/.ssh/hewentian-prod.pem

ubuntu 下 zssh 的使用

首先,ubuntu下需要安装下面两个包,如果还未安装的话:

1
2
$ sudo apt install lszrz
$ sudo apt install zssh

  1. 使用 zssh 替代 ssh 连接到目标系统,并登入:

    1
    zssh jump_server
  2. 发送文件到目标系统。比如,我们要上传a.txt文件

    1
    2
    3
    4
    5
    6
    7
    首先进入目标机的要上传到的目录,这里进入用户根目录下的Downloads
    $ cd ~/Downloads
    (然后,按 ctrl + @ 进入文件传输状态,这个时候会浏览本地机器的文件系统了)
    zssh > ls
    a.txt
    要将a.txt上传到目标机,执行如下命令即可
    zssh > sz a.txt
  3. 下载文件到本地。比如,我们想从目标系统下载 ~/Downloads/a.txt 到本地

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    $ cd ~/Downloads
    $ ls
    a.txt

    $ sz a.txt
    �B00000000000000
    (按 ctrl + @ 进入文件传输状态)
    zssh > rz
    Receiving: a.txt
    Bytes received: 7/ 7 BPS:1198

    Transfer complete

    $

在目标系统输入 sz 时,我们开启了文件发送,此处可能会有乱码,暂时不管;然后,按 Ctrl+@ 进入文件传输模式,输入 rz 并回车进行文件下载,下载完成后,自动退出文件传输模式

在自己的linux机上,如ubuntu等,安装上zssh,先用zssh登陆上跳板机,再在跳板机上ssh到相应服务器,然后ctrl+@,就可以相应上传下载文件了,先记着,后续再补详细资料。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
上传本地文件到服务器
在服务器上先cd至相应要放上传文件的目录之后

rz -bye //在远程服务器的相应目录上运行此命令,表示做好接收文件的准备
ctrl+@ //运行上面命令后,会出现一些乱码字符,不要怕,按此组合键,进入zssh
zssh > //这里切换到了本地机器
zssh > pwd //看一下本地机器的目录在那
zssh > ls //看一下有那些文件
zssh > sz 123.txt //上传本地机器的当前目录的123.txt到远程机器的当前目录

下载服务器文件到本地
sz filename //在远程机器上,启动sz, 准备发送文件
//看到一堆乱码,不要怕,这会按下组合键
ctrl+@
zssh > pwd //看看在那个目录,cd 切换到合适的目录
zssh > rz -bye //接住对应的文件

ubuntu 开放指定端口

一般情况下,ubuntu安装好的时候,iptables会被安装上,如果没有的话先安装

sudo apt-get install iptables

添加开放端口
sudo iptables -A INPUT -p tcp –dport 4412 -j ACCEPT
sudo iptables -A OUTPUT -p tcp –sport 4412 -j ACCEPT

# 临时保存配置,重启后失效
sudo iptables-save

安装iptables-persistent工具,持久化开放端口配置
sudo apt-get install iptables-persistent

sudo netfilter-persistent save
sudo netfilter-persistent reload

完成上述操作就可以永久打开我们需要的端口了

redHat 开放指定端口

同样的,我们开放4412这个端口。先检查iptables是否启动:

sudo service iptables status

Redirecting to /bin/systemctl status  iptables.service
Unit iptables.service could not be found.

安装iptables-services:

sudo yum install iptables-services

启动iptables:

sudo service iptables start

编辑配置文件,将4412端口添加到22端口下:

sudo vi /etc/sysconfig/iptables

# sample configuration for iptables service
# you can edit this manually or use system-config-firewall
# please do not ask us to add additional ports/services to this default configuration
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
-A INPUT -p icmp -j ACCEPT
-A INPUT -i lo -j ACCEPT
-A INPUT -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 4412 -j ACCEPT
-A INPUT -j REJECT --reject-with icmp-host-prohibited
-A FORWARD -j REJECT --reject-with icmp-host-prohibited
COMMIT

重启:

sudo service iptables restart

查看开放端口:

sudo iptables -nL

Linux下打开ISO文件方法

Linux下用mount挂载命令

1
$ mount -o loop /home/hewentian/Downloads/ubuntu.iso /mnt/cdrom

取消挂载

1
$ umount /mnt/cdrom

Linux 统计当前文件夹下的文件个数、目录个数

1) 统计当前文件夹下文件的个数

1
$ ls -l | grep "^-" | wc -l

2) 统计当前文件夹下目录的个数

1
$ ls -l | grep "^d" | wc -l

3) 统计当前文件夹下文件的个数,包括子文件夹里的

1
$ ls -lR | grep "^-" | wc -l

4) 统计文件夹下目录的个数,包括子文件夹里的

1
$ ls -lR | grep "^d" | wc -l

说明:

1
$ ls -l

长列表输出当前文件夹下文件信息(注意这里的文件,不同于一般的文件,可能是目录、链接、设备文件等)

1
$ grep "^-"

这里将长列表输出信息过滤一部分,只保留一般文件,如果只保留目录就是 ^d

1
$ wc -l

统计输出信息的行数,因为已经过滤得只剩一般文件了,所以统计结果就是一般文件信息的行数,又由于一行信息对应一个文件,所以也就是文件的个数。

安装openvpn

1
2
3
4
5
首先安装openvpn
$ sudo apt install openvpn

然后启动,其中~/Downloads/hewentian是你的公司下发的你自已的登录帐号相关的文件
$ sudo openvpn --config ~/Downloads/hewentian/hewentian.ovpn

这样,你在家里也可以连回公司的网络

如果要求帐号密码,又不想每次都输入,则可以建立一个文件,用于存放用户名和密码。第一行存放用户名,第二行存放密码。

1
2
3
4
5
6
$ cd ~/Downloads/hewentian/
$ touch auth-user-pass-File
$ vi auth-user-pass-File

userName
password

这样连接的命令为

1
$ sudo openvpn --config ~/Downloads/hewentian/hewentian.ovpn --auth-user-pass ~/Downloads/hewentian/auth-user-pass-File

安装forticlient VPN

有时候,公司提供的可能是forticlient VPN。这时候,就不能使用openvpn来连接啦,要安装forticlient VPN。参考:
https://kifarunix.com/install-forticlient-vpn-client-on-ubuntu-20-04-ubuntu-18-04/
https://www.forticlient.com/repoinfo

Ubuntu 18.04 LTS为例,安装命令:
Install gpg key

wget -O - https://repo.fortinet.com/repo/ubuntu/DEB-GPG-KEY | sudo apt-key add -

Add the following line in /etc/apt/sources.list

deb [arch=amd64] https://repo.fortinet.com/repo/ubuntu/ /bionic multiverse

Update package lists

sudo apt-get update

Install FortiClient

sudo apt install forticlient

linux 查询 CPU 信息

1
2
3
4
5
6
7
8
9
10
$ cat /proc/cpuinfo | grep "model name" && cat /proc/cpuinfo | grep "physical id"

model name : Intel(R) Core(TM) i3-2350M CPU @ 2.30GHz
model name : Intel(R) Core(TM) i3-2350M CPU @ 2.30GHz
model name : Intel(R) Core(TM) i3-2350M CPU @ 2.30GHz
model name : Intel(R) Core(TM) i3-2350M CPU @ 2.30GHz
physical id : 0
physical id : 0
physical id : 0
physical id : 0

linux 查询 内存大小

1
2
3
$ cat /proc/meminfo | grep MemTotal

MemTotal: 8115068 kB

linux 查询 硬盘大小

1
2
3
4
5
6
7
8
$ fdisk -l | grep Disk

Disk /dev/sda: 119.2 GiB, 128035676160 bytes, 250069680 sectors
Disklabel type: dos
Disk identifier: 0x07462b5e
Disk /dev/sdb: 465.8 GiB, 500107862016 bytes, 976773168 sectors
Disklabel type: dos
Disk identifier: 0x547aca8b

查看内存使用量和交换区使用量

1
2
3
4
$ free -m
total used free shared buff/cache available
Mem: 7924 5783 472 331 1668 1460
Swap: 15623 1176 14447

查看各分区使用情况

1
2
3
4
5
6
7
8
9
10
$ df -h
Filesystem Size Used Avail Use% Mounted on
udev 3.9G 0 3.9G 0% /dev
tmpfs 793M 9.4M 784M 2% /run
/dev/sda2 102G 27G 71G 28% /
tmpfs 3.9G 130M 3.8G 4% /dev/shm
tmpfs 5.0M 4.0K 5.0M 1% /run/lock
tmpfs 3.9G 0 3.9G 0% /sys/fs/cgroup
/dev/sda1 464M 174M 263M 40% /boot
tmpfs 793M 104K 793M 1% /run/user/1000

查看指定目录的大小

1
2
3
4
5
6
$ du -sh
4.5G .

还可以另上指定文件,这样就计算那个文件或目录的大小
$ du -sh ROOT.zip
67M ROOT.zip

gpg 验证已下载文件的真实性和完整性

首先检查系统是否已经安装GPG

1
$ dpkg-query -l gnupg*

否则使用如下命令安装(ubuntu)

1
$ sudo apt-get install gnupg

安装完毕后,生成密钥对,要使用到你的用户名和邮箱,以及保护你私钥的密码,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
$ gpg --gen-key
gpg (GnuPG) 1.4.20; Copyright (C) 2015 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Please select what kind of key you want:
(1) RSA and RSA (default)
(2) DSA and Elgamal
(3) DSA (sign only)
(4) RSA (sign only)
Your selection?
RSA keys may be between 1024 and 4096 bits long.
What keysize do you want? (2048)
Requested keysize is 2048 bits
Please specify how long the key should be valid.
0 = key does not expire
<n> = key expires in n days
<n>w = key expires in n weeks
<n>m = key expires in n months
<n>y = key expires in n years
Key is valid for? (0)
Key does not expire at all
Is this correct? (y/N) y

You need a user ID to identify your key; the software constructs the user ID
from the Real Name, Comment and Email Address in this form:
"Heinrich Heine (Der Dichter) <heinrichh@duesseldorf.de>"

Real name: Tim Ho
Email address: wentian.he@qq.com
Comment:
You selected this USER-ID:
"Tim Ho <wentian.he@qq.com>"

Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? O
You need a Passphrase to protect your secret key.

We need to generate a lot of random bytes. It is a good idea to perform
some other action (type on the keyboard, move the mouse, utilize the
disks) during the prime generation; this gives the random number
generator a better chance to gain enough entropy.
.........+++++
+++++
We need to generate a lot of random bytes. It is a good idea to perform
some other action (type on the keyboard, move the mouse, utilize the
disks) during the prime generation; this gives the random number
generator a better chance to gain enough entropy.
+++++

Not enough random bytes available. Please do some other work to give
the OS a chance to collect more entropy! (Need 73 more bytes)
+++++
gpg: key 46DC4BA0 marked as ultimately trusted
public and secret key created and signed.

gpg: checking the trustdb
gpg: 3 marginal(s) needed, 1 complete(s) needed, PGP trust model
gpg: depth: 0 valid: 2 signed: 0 trust: 0-, 0q, 0n, 0m, 0f, 2u
pub 2048R/46DC4BA0 2018-01-14
Key fingerprint = 06F1 0995 A7FE DF6F 007F CE59 B307 E8C8 46DC 4BA0
uid Tim Ho <wentian.he@qq.com>
sub 2048R/74EB06EB 2018-01-14

密钥生成完毕后,公钥和私钥都将存储在~/.gnupg目录中,供之后使用。

导入文件所有者的公钥

1
2
3
4
$ gpg --import rabbitmq-release-signing-key.asc 
gpg: key 6026DFCA: "RabbitMQ Release Signing Key <info@rabbitmq.com>" not changed
gpg: Total number processed: 1
gpg: unchanged: 1

当所有者的公钥导入完毕,它会输出一个密钥编号(比如“6026DFCA”),如上所示

现在,运行这个命令,检查已导入公钥的指纹:

1
2
3
4
5
$ gpg --fingerprint 6026DFCA
pub 4096R/6026DFCA 2016-05-17
Key fingerprint = 0A9A F211 5F46 87BD 2980 3A20 6B73 A36E 6026 DFCA
uid RabbitMQ Release Signing Key <info@rabbitmq.com>
sub 4096R/12EBCE19 2016-05-17

检查上面的指纹是否与所有者官网提供的一致。

下面的步骤可选,

1
2
3
4
5
6
7
8
9
10
$ gpg --edit-key 6026DFCA
gpg (GnuPG) 1.4.20; Copyright (C) 2015 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.


pub 4096R/6026DFCA created: 2016-05-17 expires: never usage: SC
trust: full validity: unknown
sub 4096R/12EBCE19 created: 2016-05-17 expires: never usage: E
[ unknown] (1). RabbitMQ Release Signing Key <info@rabbitmq.com>

在GPG提示符下键入“trust”,这会让你可以选择该密钥的信任级别:从1到5,这里选择4

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
gpg> trust
pub 4096R/6026DFCA created: 2016-05-17 expires: never usage: SC
trust: full validity: unknown
sub 4096R/12EBCE19 created: 2016-05-17 expires: never usage: E
[ unknown] (1). RabbitMQ Release Signing Key <info@rabbitmq.com>

Please decide how far you trust this user to correctly verify other users' keys
(by looking at passports, checking fingerprints from different sources, etc.)

1 = I don't know or won't say
2 = I do NOT trust
3 = I trust marginally
4 = I trust fully
5 = I trust ultimately
m = back to the main menu

Your decision? 4

pub 4096R/6026DFCA created: 2016-05-17 expires: never usage: SC
trust: full validity: unknown
sub 4096R/12EBCE19 created: 2016-05-17 expires: never usage: E
[ unknown] (1). RabbitMQ Release Signing Key <info@rabbitmq.com>

gpg> sign

pub 4096R/6026DFCA created: 2016-05-17 expires: never usage: SC
trust: full validity: unknown
Primary key fingerprint: 0A9A F211 5F46 87BD 2980 3A20 6B73 A36E 6026 DFCA

RabbitMQ Release Signing Key <info@rabbitmq.com>

Are you sure that you want to sign this key with your
key "Tim Ho <wentian.he@qq.com>" (E99DCF91)

Really sign? (y/N) y

You need a passphrase to unlock the secret key for
user: "Tim Ho <wentian.he@qq.com>"
2048-bit RSA key, ID E99DCF91, created 2018-01-14

gpg> save

然后sign,最后save,这里输入的passphrase错误,与我之前的密码不符,未明原因。
最后,查看导入的keys

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$ gpg --list-keys
/home/hewentian/.gnupg/pubring.gpg
----------------------------------
pub 2048R/E99DCF91 2018-01-14
uid Tim Ho <wentian.he@qq.com>
sub 2048R/6F7627AD 2018-01-14

pub 4096R/6026DFCA 2016-05-17
uid RabbitMQ Release Signing Key <info@rabbitmq.com>
sub 4096R/12EBCE19 2016-05-17

pub 2048R/46DC4BA0 2018-01-14
uid Tim Ho <wentian.he@qq.com>
sub 2048R/74EB06EB 2018-01-14

最后:验证文件的真实性/完整性

1
2
3
4
5
6
7
8
9
$ gpg --verify rabbitmq-server_3.7.2-1_all.deb.asc rabbitmq-server_3.7.2-1_all.deb
gpg: Signature made Sat 23 Dec 2017 03:03:34 PM CST using RSA key ID 6026DFCA
gpg: checking the trustdb
gpg: 3 marginal(s) needed, 1 complete(s) needed, PGP trust model
gpg: depth: 0 valid: 2 signed: 0 trust: 0-, 0q, 0n, 0m, 0f, 2u
gpg: Good signature from "RabbitMQ Release Signing Key <info@rabbitmq.com>"
gpg: WARNING: This key is not certified with a trusted signature!
gpg: There is no indication that the signature belongs to the owner.
Primary key fingerprint: 0A9A F211 5F46 87BD 2980 3A20 6B73 A36E 6026 DFCA

该命令的输出里面含有“Good signature from ”,这表明已下载的.deb文件已成功通过了验证。要是已下载文件在签名生成后以任何一种方式而遭到篡改,验证就会失败。

Linux如何运行.AppImage文件

AppImage是新型的打包软件,它可以解决Linux上面的依赖问题。在使用上面相比其他的软件使用极为简单。
首先给它增加可执行权限,然后执行即可。如下:

1
2
$ chmod +x {AppImage文件}
$ ./{AppImage文件}

yum切换为阿里的源

有时候,我们下载软件慢,可以切换到阿里的yum.
首先备份现有的源,以便还原。

1
2
$ cd /etc/yum.repos.d/
$ mv CentOS-7.repo CentOS-7.repo_bak

下载阿里的源

1
$ wget -O /etc/yum.repos.d/CentOS-7.repo http://mirrors.aliyun.com/repo/Centos-7.repo

然后执行如下命令即可

1
2
3
4
$ yum remove epel-release
$ yum clean all
$ yum makecache
$ yum -y install epel-release

在处理python图片的时候,如果提示某些属性不可用,可以升级Pillow

1
2
3
$ pip uninstall Pillow
$ pip install --upgrade pip 或者 $ pip install pip==9.0.1
$ pip install Pillow

linux拆分文件

linux拆分文件可以使用split命令,既可以按行拆分,又可以按大小拆分。例如有一个文件,它有1000行,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
$ cat mydata.txt 
1 ----------------
2 ----------------
3 ----------------
4 ----------------
5 ----------------
6 ----------------
7 ----------------
8 ----------------
9 ----------------
10 ----------------
...
...
...
991 ----------------
992 ----------------
993 ----------------
994 ----------------
995 ----------------
996 ----------------
997 ----------------
998 ----------------
999 ----------------
1000 ----------------

我们将文件按行拆分,每100行一个文件,后缀有3位数字,以数字递增,后缀为mydata_

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
$ ls
mydata.txt

$ split -l 100 mydata.txt -d -a 3 mydata_
$ ls
mydata_000 mydata_001 mydata_002 mydata_003 mydata_004 mydata_005 mydata_006 mydata_007 mydata_008 mydata_009 mydata.txt

$ wc -l *
100 mydata_000
100 mydata_001
100 mydata_002
100 mydata_003
100 mydata_004
100 mydata_005
100 mydata_006
100 mydata_007
100 mydata_008
100 mydata_009
1000 mydata.txt
2000 total

我们将文件按大小拆分,每个文件5k,后缀有3位数字,以数字递增,后缀为mydata_

1
2
3
4
5
6
7
8
9
10
11
12
$ ll mydata.txt 
-rw-r--r-- 1 hewentian hewentian 20893 Aug 5 15:28 mydata.txt

$ split -b 5k mydata.txt -d -a 3 mydata_

$ ll mydata*
-rw-r--r-- 1 hewentian hewentian 5120 Aug 5 17:39 mydata_000
-rw-r--r-- 1 hewentian hewentian 5120 Aug 5 17:39 mydata_001
-rw-r--r-- 1 hewentian hewentian 5120 Aug 5 17:39 mydata_002
-rw-r--r-- 1 hewentian hewentian 5120 Aug 5 17:39 mydata_003
-rw-r--r-- 1 hewentian hewentian 413 Aug 5 17:39 mydata_004
-rw-r--r-- 1 hewentian hewentian 20893 Aug 5 15:28 mydata.txt

将文件拆分成指定数目的小文件,使用-n参数

1
$ split -n 5 mydata.txt -d -a 3 mydata_

linux合并文件

可以使用cat命令从文件中读入两个文件,然后将其重定向到一个新的文件。
用法示例,将file1.txtfile2.txt合并到file.txt

1
$ cat file1.txt file2.txt > file.txt

其中,file.txt可以不存在,会被自动创建。file1.txtfile2.txt的顺序决定了它们在file.txt中的顺序。

也可以只使用cat命令读入一个文件,然后使用>>将文本流追加到另一个文件的末位。
用法示例,将file1.txt追加到file2.txt的末尾:

1
$ cat file1.txt >> file2.txt

Linux scp命令

Linux scp命令用于Linux之间复制文件和目录。
scp是 secure copy的缩写, scp是linux系统下基于ssh登陆进行安全的远程文件拷贝命令
1、从本地复制到远程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
命令格式:
scp local_file remote_username@remote_ip:remote_folder
或者
scp local_file remote_username@remote_ip:remote_file
或者
scp local_file remote_ip:remote_folder
或者
scp local_file remote_ip:remote_file

默认使用22端口,如果是其他端口,请使用-P指定
scp -P 12022 local_file remote_ip:remote_file

复制目录命令格式:
scp -r local_folder remote_username@remote_ip:remote_folder
或者
scp -r local_folder remote_ip:remote_folder

从远程复制到本地
从远程复制到本地,只要将从本地复制到远程的命令的后2个参数调换顺序即可,如下实例

1
2
$ scp root@192.168.1.100:/home/root/a.txt /home/hewentian/Documents/
$ scp -r root@192.168.1.100:/home/root/a/ /home/hewentian/Documents/

cat, more, less的区别

more功能类似cat,cat命令是整个文件的内容从上到下显示在屏幕上。more会以一页一页的显示方便使用者逐页阅读,而最基本的指令就是按空白键(space)就往下一页显示,按b键就会往回(back)一页显示,而且还有搜寻字串的功能 。more命令从前向后读取文件,因此在启动时就加载整个文件。
less与more类似,但使用less可以随意浏览文件,而more仅能向前移动,却不能向后移动,而且less在查看之前不会加载整个文件。

find 命令将查找到的文件执行操作

这里将当前目录下(包括子目录)的所有以.txt结尾的文件删掉

1
find . -name "*.txt" -exec rm {} \;

Several methods to execute shell scripts

  1. . scriptFileName (needn’t excute permission,the script file is under current directory, executing in current shell)
  2. sh scriptFileName ( needn’t execute permission,the script file is under current directory , create a child process to execute the script file)
  3. ./scriptFileName ( need execute permission,the script file is under current directory )
  4. scriptFileName ( need execute permission, the script file is in directory which listed in PATH)

查看文件编码file命令

1
2
3
4
5
$ file -i tmp.txt 
tmp.txt: text/plain; charset=utf-8

$ file -i a.txt
a.txt: text/plain; charset=iso-8859-1

Linux环境下打开来自Windows的文本文件出现乱码

使用iconv命令,将目标文件编码方式转为UTF-8,命令如下:

1
2
3
$ iconv -f gbk -t utf8 -o outputFile sourceFile

其实,outputFile、sourceFile的名字可以相同,这样就将原文件的编码修改了

sed命令修改文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# 将beforeStr修改为afterStr,保存为新的文件work2.txt
$ sed 's/beforeStr/afterStr/g' work.txt > work2.txt

# 覆盖原来的文件,即在原来的文件修改
$ sed -i 's/beforeStr/afterStr/g' work.txt

# 删除文件第1行
$ sed -i '1d' filename

# 删除第n行
$ sed -i 'nd' filename

# 删除最后一行
$ sed -i '$d' filename

# 删除文件中包含某个关键字的所有行
$ sed -i '/word/d' filename

# 删除文件中包含某个关键字开头的所有行
$ sed -i '/^word/d' filename

# 在文档指定行中增加一行
$ sed -i '/* /a*' filename

示例:
$ more ent.txt
11111
22222
33333
55555

$ sed -i '/33/a44444' ent.txt
$ more ent.txt
11111
22222
33333
44444
55555

sed命令提取文件中指定格式的数据

有文件内容如下:
2020-05-28 17:49:22,416 [com.hewentian.crawler.DayCrawler] [WARN] - {“date”:”2020-01-01”,”type”:1}
2020-05-28 17:49:27,419 [com.hewentian.crawler.DayCrawler] [WARN] - {“date”:”2020-01-01”,”type”:2}

我想提取花括号中的内容,命令如下:

1
2
3
4
$ sed 's/^.*\({.*}\).*/\1/g' dayError.log

{"date":"2020-01-01","type":1}
{"date":"2020-01-01","type":2}

去除重复的行

可以联合使用sort和uniq命令,uniq只会去除连续重复的行。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
$ cat ent.txt 
22222
11111
55555
55555
33333
44444
44444
11111
aaaaa

$ uniq ent.txt
22222
11111
55555
33333
44444
11111
aaaaa

$ sort ent.txt | uniq
11111
22222
33333
44444
55555
aaaaa

或仅显示有重复的行
$ sort ent.txt | uniq -d
11111
44444
55555

找出两个文件中内容不同的部分并输出

查找在b.txt文件中存在,在a.txt文件中不存在的内容,并输出到文件diff.txt。依次执行如下命令:

1
2
3
4
5
$ sort -r a.txt -o a.txt
$ sort -r b.txt -o b.txt
$ script diff.txt
$ grep -vFf a.txt b.txt
$ exit

Ubuntu 中卸载软件的几种命令

参考:https://blog.csdn.net/dzjian_/article/details/79768813

1、在终端里通过 apt-get 安装的软件:

安装软件:sudo apt-get install softname1 softname2 softname3 ……
卸载软件:sudo apt-get remove softname1 softname2 softname3 ……
卸载并清除配置:sudo apt-get remove --purge softname1
更新软件信息数据库:sudo apt-get update
进行系统升级:sudo apt-get upgrade, sudo apt-get distupgrade
搜索软件包:sudo apt-cache search softname1 softname2 softname3 ……

2、在终端里通过 deb 安装的软件:

安装deb软件包:dpkg -i softname.deb
删除软件包:dpkg -r softname.deb
删除配置文件:dpkg --purge softname.deb    注意:-r 和 --purge不能同时使用,先删除软件包,再删除配置文件
查看软件包信息:dpkg -info softname.deb
查看文件拷贝详情:dpkg -L softname.deb
查看系统中已安装软件包信息:dpkg -l
重新配置软件包:dpkg -reconfigure softname

3、卸载源代码编译的的软件:

cd 源代码目录
make clean
./configure
(make)
make uninstall
rm -rf 目录

4、清理系统:

sudo apt-get autoclean     将已经删除了的软件包的.deb安装文件从硬盘中删除掉
sudo apt-get clean         会把你已安装的软件包的安装包也删除掉,当然多数情况下这些包没什么用了
sudo apt-get autoremove    删除为了满足其他软件包的依赖而安装的,但现在不再需要的软件包

linux系统ssh免密码登录另一台linux机器执行某个脚本

例如,我要在本机通过ssh免密执行一个在IP为192.168.30.241的linux机器上的脚本,目标机器的用户为root,SSH端口为:12022

首先,需要将本机的公钥文件id_rsa.pub的内容追加到主机192.168.30.241上的~/.ssh/authorized_keys文件中。如果本机没有该公钥文件,可通过如下命令产生:

1
$ ssh-keygen -t rsa -C "youremail@example.com"

上述命令执行后,本机目录~/.ssh下会出现两个文件:id_rsa和id_rsa.pub。其中,id_rsa.pub为公钥文件。

将本机的id_rsa.pub文件传到192.168.30.241上:

1
2
3
$ scp -P 12022 /home/hewentian/.ssh/id_rsa.pub root@192.168.30.241:/tmp/id_rsa.pub
root@192.168.30.241's password:
id_rsa.pub 100% 399 0.4KB/s 00:00

192.168.30.241机器上:

1
2
$ su root
$ cat /tmp/id_rsa.pub >> ~/.ssh/authorized_keys

接下来,就可以在本机不输入密码的情况下SSH执行在远程主机192.168.30.241中的命令了。命令格式如下:

直接登录远程的机器:ssh -p 端口号 远程用户名@远程主机名或IP地址
只执行在远程机器的命令:ssh -p 端口号 远程用户名@远程主机名或IP地址 '远程命令或者脚本'

例如:

ssh -p 12022 root@192.168.30.241
ssh -p 12022 root@192.168.30.241 'hostname'
ssh -p 12022 root@192.168.30.241 '/root/test.sh'
ssh -p 12022 root@192.168.30.241 'source /etc/profile > /dev/null; cd /root/; sh test.sh'

注意:当远程脚本中使用了一些命令依赖于环境变量时,该脚本需要在其第一行中包含执行profile文件的命令:

1
2
3
$ source /etc/profile
或者
$ source ~/.bash_profile

否则,远程脚本可能报错。

FTP工具filezilla

在Ubuntu上面安装filezilla还是很方便的,首先检查系统是否已安装此软件:

1
2
3
$ filezilla
The program 'filezilla' is currently not installed. You can install it by typing:
sudo apt install filezilla

由上可知,系统中并未安装此filezilla,我们按提示安装即可:

1
2
3
4
5
6
7
8
9
10
11
12
$ sudo apt install filezilla
[sudo] password for hewentian:
Reading package lists... Done
Building dependency tree
Reading state information... Done
...
...
...
Setting up libwxbase3.0-0v5:amd64 (3.0.2+dfsg-1.3) ...
Setting up libwxgtk3.0-0v5:amd64 (3.0.2+dfsg-1.3) ...
Setting up filezilla (3.15.0.2-1ubuntu1) ...
Processing triggers for libc-bin (2.23-0ubuntu10) ...

安装成功后,使用很简单。在命令行中直接输入filezilla即可。

ubuntu安装小便签

我们选择安装indicator-stickynotes,这个可以在
http://ppa.launchpad.net/umang/indicator-stickynotes/ubuntu/pool/main/i/indicator-stickynotes/
下载,我们下载目前的最新版本indicator-stickynotes_1.0.0-0_ppa1_all.deb
安装方法也很简单:

1
$ sudo dpkg -i indicator-stickynotes_1.0.0-0_ppa1_all.deb

启动方式可以直接在命令行中输入indicator-stickynotes,当然也可以在资源管理器中查找:

ubuntu下面,微信的使用

微信的官网好像没有Linux版本下载,但是可以在以下连接下载到:
https://github.com/geeeeeeeeek/electronic-wechat
下载相应版本后,解压后,即可使用。

截屏软件

shutter是值得推荐的一款截图软件,功能丰富,堪称神器,安装方式如下:

1
$ sudo apt-get install shutter

在Ubuntu 18.04中安装后,发现编辑按钮变编程灰色。Shutter需要libgoo-canvas-perl库,该库在Ubuntu 18.04主存档中不可用,解决方法:

下载下面这三个软件,前两个可能系统已经安装。
https://launchpad.net/ubuntu/+archive/primary/+files/libgoocanvas-common_1.0.0-1_all.deb
https://launchpad.net/ubuntu/+archive/primary/+files/libgoocanvas3_1.0.0-1_amd64.deb
https://launchpad.net/ubuntu/+archive/primary/+files/libgoo-canvas-perl_0.06-2ubuntu3_amd64.deb

sudo dpkg -i libgoocanvas-common_1.0.0-1_all.deb 
sudo dpkg -i libgoocanvas3_1.0.0-1_amd64.deb 
sudo dpkg -i libgoo-canvas-perl_0.06-2ubuntu3_amd64.deb
sudo apt --fix-broken install 
sudo dpkg -i libgoocanvas3_1.0.0-1_amd64.deb 

重启电脑生效。

录屏软件

Simple Screen Recorder是一款简单的屏幕录像工具,能够在屏幕上录制视频、教程,界面简单,功能够用。安装的过程可能有点慢,请耐心等待,并多试几次。

1
2
3
$ sudo add-apt-repository ppa:maarten-baert/simplescreenrecorder
$ sudo apt-get update
$ sudo apt-get install simplescreenrecorder

系统监视器

它可以实时查看电脑的cpu、内存占用率、温度等等,非常方便,还可以自已定制要显示的内容。

1
2
3
$ sudo add-apt-repository ppa:fossfreedom/indicator-sysmonitor
$ sudo apt-get update
$ sudo apt-get install indicator-sysmonitor

下载软件

ubuntu上面目前没有迅雷可用,但是可以使用uget:

1
2
3
$ sudo add-apt-repository ppa:plushuang-tw/uget-stable
$ sudo apt-get update
$ sudo apt-get install uget

代理软件

推荐使用 shadowsocks:

1
2
3
$ sudo add-apt-repository ppa:hzwhuang/ss-qt5
$ sudo apt-get update
$ sudo apt-get install shadowsocks-qt5

当然,这仅是工具,你还得有相关帐号。

Markdown编辑器

ubuntu上面一个好用的markdown编辑器typora:

1
2
3
4
$ sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys BA300B7755AFCFAE
$ sudo add-apt-repository 'deb https://typora.io ./linux/'
$ sudo apt-get update
$ sudo apt-get install typora

剪贴板软件

clipit非常好用,在设置中记得将Automatically paste selected item选上,否则选中了不会自动粘贴:

1
2
3
$ sudo add-apt-repository ppa:shantzu/clipit
$ sudo apt-get update
$ sudo apt-get install clipit

图片编辑器

ubuntu上可以使用GIMP,好用:

1
$ sudo apt-get install gimp

思维导图 Xmind

http://www.xmind.net/download/linux/ 下载 xmind-8-update8-linux.zip,解压后即可使用。

ubuntu18.04怎么设置字体样式,调整字体大小

安装gnome-tweaks桌面配置工具

1
sudo apt install gnome-tweaks

alt+f2 在运行窗口输入 gnome-tweaks 命令,然后回车。

ubuntu 18.04系统设置应用到桌面快捷方式的使用方法

首先在系统文件夹/usr/share/applications中找到对应的desktop文件,将其复制到桌面文件夹即可,如果找不到对应文件则需要按如下步骤生成desktop文件。

  1. “Ctrl+Alt+t”打开终端,输入命令:gnome-desktop-item-edit;如果显示不存在,则需要安装命令:sudo apt install gnome-panel

  2. 安装完成后执行创建快捷方式:gnome-desktop-item-edit ~/Desktop/ –create-new,弹出对话框后,填入和选择相应的参数及路径。

ubuntu18.04将最小、最大、关闭按钮放到左边

gsettings set org.gnome.desktop.wm.preferences button-layout 'minimize,maximize,close:' 

ubuntu18.04安装nvidia显卡

参考:https://linuxconfig.org/how-to-install-the-nvidia-drivers-on-ubuntu-18-04-bionic-beaver-linux

First, detect the model of your nvidia graphic card and the recommended driver. To do so execute:

1
2
3
4
5
6
$ ubuntu-drivers devices
== /sys/devices/pci0000:00/0000:00:1c.0/0000:01:00.0 ==
modalias : pci:v000010DEd00001D12sv00001D72sd00001703bc03sc02i00
vendor : NVIDIA Corporation
driver : nvidia-driver-390 - distro non-free recommended
driver : xserver-xorg-video-nouveau - distro free builtin

From the above output we can conclude that the current system has NVIDIA graphic card installed and the recommend driver to install is nvidia-driver-390.

If you agree with the recommendation feel free to use ubuntu-drivers command again to install all recommended drivers:

$ sudo ubuntu-drivers autoinstall

Alternatively, install desired driver selectively using the apt command. For example:

$ sudo apt install nvidia-driver-390

Once the installation is concluded, reboot your system and you are done.

免密登录远程主机

将本地公钥添加到远程主机的authorized_keys中,例如远程主机为 192.168.1.123,然后就可以ssh免密登录过去了

1
2
3
$ ssh-copy-id 192.168.1.123

$ ssh 192.168.1.123

Ubuntu 18.04 解决耳机插入没有声音的问题

下载pulseaudio音量控制软件配置驱动即可。

1
$ sudo apt install pavucontrol

安装后进入配置选项,将内置音频的声卡安装选为模拟立体声双工即可。
或者进入Output Devices -> Port选择Headphones(unplugged)这里耳机就会有声音,而电脑自带扬声器没声。

Ubuntu 18.04禁用关闭笔记本盖子自动待机

1
2
3
4
5
6
$ sudo vi /etc/systemd/logind.conf

将其中的:
#HandleLidSwitch=suspend
改成:
HandleLidSwitch=ignore

之后重启systemd-logind

1
$ sudo service systemd-logind restart

ok.

设置日期和时间

在ubuntu下可以通过以下命令设置时间日期,或者使用NTP进行时间同步

1
2
$ timedatectl set-ntp no
$ timedatectl set-time '2019-01-23 16:01:23'

awk的使用

它可以将文件内容按指定的分隔符进行输出,例如有文件a.txt,其内容如下:

1###abc
2###def
3###ghi

如果我要以###为分隔符提取数据,可以这样:

1
2
3
4
5
$ cat a.txt | awk -F'###' '{print $1,$2}'

1 abc
2 def
3 ghi

也可以单独提取某一列。

Linux下通过一行命令查找并杀掉进程

如果我们运行了一个进程:

1
$ nohup java -jar he-app.jar 2>&1 &

通过一条命令杀掉它:

1
$ ps -ef | grep he-app.jar | grep -v grep | awk '{print $2}' | xargs kill -9

测试网速的工具

可以使用speedtest-cli这个工具来测试,如果还未安装,可使用如下命令安装:

1
2
$ sudo apt install python-pip
$ sudo pip install speedtest-cli

使用也好简单:

1
2
3
4
5
6
7
8
9
10
11
$ speedtest-cli 

Retrieving speedtest.net configuration...
Testing from China Unicom Guangdong province (58.249.3.236)...
Retrieving speedtest.net server list...
Selecting best server based on ping...
Hosted by ChinaTelecom-GZ (Guangzhou) [2.51 km]: 20.736 ms
Testing download speed................................................................................
Download: 8.25 Mbit/s
Testing upload speed................................................................................................
Upload: 9.03 Mbit/s

linux下面合并图片

垂直方向合并:

convert -append image1.png image2.png image3.png result.png

垂直方向合并:

convert +append image1.png image2.png image3.png result.png

通过shadowsocks访问Google

首先你得在海外有一台机器(假设IP为 111.112.113.114),在该机器上面安装shadowsocks服务端:

1
2
3
4
5
6
$ yum -y install epel-release
$ yum install -y yum-utils
$ yum-config-manager --enable epel
$ yum install -y python-pip
$ pip install --upgrade pip
$ pip install shadowsocks

配置服务端:

1
2
3
4
5
6
7
8
9
10
11
$ vi shadowsocks.json 
{
"server":"111.112.113.114",
"server_port":10086,
"local_address": "127.0.0.1",
"local_port":1080,
"password":"myPassword",
"timeout":300,
"method":"aes-256-cfb",
"fast_open": false
}

在后台启动:

1
$ ssserver -c shadowsocks.json -d start

如果服务器端有安装docker,也可以通过docker方式,用两条命令完成安装:

1
2
3
4
5
6
7
8
9
10
11
12
13
$ docker pull shadowsocks/shadowsocks-libev

$ docker run -d \
--name ss-server \
-p 4343:4343 \
-p 4343:4343/udp \
-e SERVER_ADDR=0.0.0.0 \
-e SERVER_PORT=4343 \
-e METHOD=aes-256-cfb \
-e PASSWORD="abcd1234*#(" \
-e TIMEOUT=300 \
-e DNS_ADDRS="8.8.8.8,8.8.4.4" \
shadowsocks/shadowsocks-libev

然后在客户端(用户本机)安装shadowsocks

1
$ sudo apt install shadowsocks

配置shadowsocks要连接的海外主机:

1
2
3
4
5
6
7
8
9
10
11
12
13
$ cd /home/hewentian/ProjectD/
$ touch shadowsocks.json
$ vi shadowsocks.json

{
"server":"111.112.113.114",
"server_port":10086,
"local_address": "127.0.0.1",
"local_port":1080,
"password":"myPassword",
"timeout":300,
"method":"aes-256-cfb"
}

然后,启动本地的服务shadowsocks:

1
2
3
4
5
$ sslocal -c shadowsocks.json

INFO: loading config from shadowsocks.json
2019-05-10 09:31:46 INFO loading libcrypto from libcrypto.so.1.1
2019-05-10 09:31:46 INFO starting local at 127.0.0.1:1080

最后,还要在电脑中配置代理,如下图:

这样,就可以正常访问Google了。

修改ubuntu 18.04的sources.list源为阿里

有时候,我们安装软件,会遇到找不到可用的安装包的情况,如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
$ cc

Command 'cc' not found, but can be installed with:

sudo apt install gcc
sudo apt install clang
sudo apt install pentium-builder
sudo apt install tcc

$ sudo apt install gcc

E: Failed to fetch http://cn.archive.ubuntu.com/ubuntu/pool/main/g/gcc-8/libmpx2_8.2.0-1ubuntu2~18.04_amd64.deb 404 Not Found [IP: 91.189.91.23 80]
E: Failed to fetch http://cn.archive.ubuntu.com/ubuntu/pool/main/g/gcc-8/libquadmath0_8.2.0-1ubuntu2~18.04_amd64.deb 404 Not Found [IP: 91.189.91.23 80]
E: Failed to fetch http://cn.archive.ubuntu.com/ubuntu/pool/main/g/gcc-7/libgcc-7-dev_7.3.0-27ubuntu1~18.04_amd64.deb 404 Not Found [IP: 91.189.91.23 80]
E: Failed to fetch http://cn.archive.ubuntu.com/ubuntu/pool/main/g/gcc-7/gcc-7_7.3.0-27ubuntu1~18.04_amd64.deb 404 Not Found [IP: 91.189.91.23 80]
E: Failed to fetch http://cn.archive.ubuntu.com/ubuntu/pool/main/g/gcc-defaults/gcc_7.3.0-3ubuntu2.1_amd64.deb 404 Not Found [IP: 91.189.91.23 80]
E: Failed to fetch http://security.ubuntu.com/ubuntu/pool/main/l/linux/linux-libc-dev_4.15.0-39.42_amd64.deb 404 Not Found [IP: 91.189.91.23 80]
E: Aborting install.

按提示进行安装,却报404。这时候,可以考虑将源修改为国内的,例如阿里的源:

1
2
3
4
5
6
7
8
9
10
11
$ cd /etc/apt/
$ sudo cp sources.list sources.list_bak
$ sudo vi sources.list

在文件的最后,加上下面的内容:
# https://opsx.alibaba.com/mirror
deb https://mirrors.aliyun.com/ubuntu/ bionic main restricted universe multiverse
deb https://mirrors.aliyun.com/ubuntu/ bionic-security main restricted universe multiverse
deb https://mirrors.aliyun.com/ubuntu/ bionic-updates main restricted universe multiverse
deb https://mirrors.aliyun.com/ubuntu/ bionic-proposed main restricted universe multiverse
deb https://mirrors.aliyun.com/ubuntu/ bionic-backports main restricted universe multiverse

最后,删除缓存,然后更新一下:

1
2
3
4
$ sudo rm -rf /var/lib/apt/lists/

$ sudo apt-get update
$ sudo apt-get upgrade

redHat升级内核

有时候,系统内核太低了,在安装某些软件后,会提示:

kernel too old

导致无法使用。这时就要升级系统的内核了。这里以redHat为例。

  1. 查看系统当前内核版本:

    uname -r
    
  2. 更新nss:

    sudo yum update nss
    
  3. 安装elrepo的yum源,升级内核需要使用elrepo的yum源,在安装yum源之前还需要我们导入elrepo的key:

    sudo rpm --import https://www.elrepo.org/RPM-GPG-KEY-elrepo.org
    sudo rpm -Uvh http://www.elrepo.org/elrepo-release-6-8.el6.elrepo.noarch.rpm
    
  4. 升级内核。在yum的elrepo源中有ml和lt两种内核,其中ml(mainline)为最新版本的内核,lt为长期支持的内核。

安装ml内核使用如下命令:

yum --enablerepo=elrepo-kernel -y install kernel-ml

安装lt内核使用如下命令:

yum --enablerepo=elrepo-kernel -y install kernel-lt

此处选择lt内核:

sudo yum --enablerepo=elrepo-kernel -y install kernel-lt
  1. 修改grub.conf文件,内核升级完后需要修改内核的启动顺序。

    sudo vi grub.conf
    default=1 改为 default=0
    
  2. 重启系统:

    sudo reboot
    

top命令

top命令在执行过程中可以使用的一些交互命令:

c    切换显示命令名称和完整命令行
M    根据驻留内存大小进行排序
P    根据CPU使用百分比大小进行排序
k    终止一个进程。系统将提示用户输入需要终止的进程PID,以及需要发送给该进程什么样的信号。一般的终止进程可以使用15信号;如果不能正常结束那就使用信号9强制结束该进程。默认值是信号15。在安全模式中此命令被屏蔽

top常用命令参数
top 每隔5秒显式所有进程的资源占用情况
top -d 2 每隔2秒显式所有进程的资源占用情况
top -c 每隔5秒显式进程的资源占用情况,并显示进程的命令行参数(默认只有进程名)
top -p 3306 -p 6378 每隔5秒显示pid是3306和pid是6379的两个进程的资源占用情况
top -d 2 -c -p 6379 每隔2秒显示pid是6379的进程的资源使用情况,并显示该进程启动的命令行参数

linux创建和删除用户

创建用户
useradd -m username 创建用户,要加-m参数才会在/home目录下创建用户目录
passwd username 为useradd创建的用户设置密码
adduser username 创建用户,自动会在/home目录下创建用户目录,但是它一创建用户,就会要求输入密码

删除用户
若使用userdel username命令删除用户时,并不能删除该用户的所有信息,只是删除了/etc/passwd、/etc/shadow、/etc/group/、/etc/gshadow四个文件里的该账户和组的信息。默认情况下创建一个用户账号,会创建一个home目录和一个用户邮箱(在/var/spool/mail目录以用户名命名)。下次再创建用户时,就会出现:该用户已存在的提示。

正确删除用户
userdel -r username

使用msmtp发送邮件

安装

From source
CentOS repository doesn’t have a RPM package for MSMTP so we need to install it from source:

yum -y install make pkgconfig gcc gcc-c++ gnutls gnutls-devel gnutls-utils openssl openssl-devel libidn libidn-devel
wget https://marlam.de/msmtp/releases/msmtp-1.8.12.tar.xz
tar xJvf msmtp-1.8.12.tar.xz
cd msmtp-1.8.12/
./configure --with-ssl=openssl
make
make install

On Ubuntu/Debian distribution use apt-get:

sudo apt-get install msmtp

配置
The configuration file of MSMTP is stored in ~/.msmtprc for each user and /etc/msmtprc is the system wide configuration file. Open the configuration file in your directory.

vi ~/.msmtprc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
defaults
tls on
logfile /var/log/msmtp.log

account th
host smtp.exmail.qq.com
port 465
auth on
tls on
tls_starttls off
tls_certcheck off
from test@th.com
user test@th.com
password yourThPassw0rd

account default: th

This file can also have more than one account, just ensure that the “account” value is unique for each section. When sending with -a {accountId} to specific the account. Save the file and use chmod to make this file readable only by the owner since it contains passwords. This step is mandatory because msmtp won’t run if the permissions are more than 600.

chmod 600 ~/.msmtprc

check from the command-line to ensure it works properly. To do this:

echo -e "Subject: test msmtp\r\n\r\nThis is a test for th." | /usr/bin/msmtp -d -C ~/.msmtprc -t wentian.he@qq.com
echo -e "Subject: test msmtp\r\n\r\nThis is a test for th." | /usr/bin/msmtp -d -C ~/.msmtprc -t wentian.he@qq.com,other@qq.com    # 可以同时给多个地址发邮件

if everything is setup correctly, you can copy this file to the/etc directory, but this is option:

sudo cp ~/.msmtprc /etc/.msmtprc

监控系统磁盘、CPU、内存使用量

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
############################################################
# */10 * * * * /bin/sh /home/hewentian/system_monitor.sh
############################################################

#!/bin/sh

ip=$(ifconfig enp1s0 | grep "inet " | awk -F ' ' '{print $2}')

msg=""

# 获取磁盘使用量,记得修改下面的磁盘编号
disk_total=$(df -h | grep "dev/sda1" | awk -F ' ' '{print $2}')
disk_used=$(df -h | grep "dev/sda1" | awk -F ' ' '{print $3}')
disk_used_percent=$(df -h | grep "dev/sda1" | awk -F '[ %]+' '{print $5}')
echo "disk used: ${disk_used} / ${disk_total}, ${disk_used_percent}%"

# 获取内存使用占比
mem_total=$(free -m | grep Mem | awk -F ' ' '{print $2}')
mem_used=$(free -m | grep Mem | awk -F ' ' '{print $3}')
mem_used_percent=$(awk 'BEGIN{printf "%.0f\n",('$mem_used'/'$mem_total')*100}')
echo "mem used: ${mem_used}M / ${mem_total}M, ${mem_used_percent}%"

# 获取CPU使用率
cpu_idle=$(top -n 1 | grep Cpu | awk '{print $8}' | cut -f 1 -d '.')
echo "cpu idle: ${cpu_idle}"


# 下面进行判断
if [ $disk_used_percent -gt 10 ];then
msg="disk used: ${disk_used} / ${disk_total}, ${disk_used_percent}%"
fi

if [ $mem_used_percent -gt 30 ];then
msg=$msg"\nmem used: ${mem_used}M / ${mem_total}M, ${mem_used_percent}%"
fi

if [ $cpu_idle -lt 99 ];then
msg=$msg"\ncpu idle: ${cpu_idle}%"
fi

echo ""

if [ -n "$msg" ]; then
msg="ip: ${ip}\n"$msg
echo "${msg}"
echo "Subject: system monitor\r\n\r\n${msg}" | /usr/bin/msmtp -d -C ~/.msmtprc -t wentian.he@qq.com
fi

获取本机的公网IP

curl ifconfig.me
curl cip.cc
curl ipinfo.io
curl myip.ipip.net

ubuntu播放rmvb视频问题

如果出现如下问题:
The playback of this movie requires a realmedia demuxer plugin which is not installed.

可执行如下命令修复:
sudo apt install libdvdnav4 libdvd-pkg gstreamer1.0-plugins-bad gstreamer1.0-plugins-ugly libdvd-pkg
sudo apt install ubuntu-restricted-extras
sudo dpkg-reconfigure libdvd-pkg

或者安装新的播放器:
sudo apt-get install vlc

unattended-upgrade进程的CPU占用100%

当用top查看CPU占用太高的进程时,如果看到:

/usr/bin/python3 /usr/bin/unattended-upgrade --download-only

解决方法:

sudo vi /etc/apt/apt.conf.d/10periodic
sudo vi /etc/apt/apt.conf.d/20auto-upgrades

APT::Periodic::Unattended-Upgrade "1"中的1改成0,重启即可。

pulseaudio进程的CPU占用40%

当用top查看CPU占用太高的进程时,如果看到:

/usr/bin/pulseaudio --start --log-target=syslog

解决方法:

sudo vi /var/lib/gdm/.pulse/client.conf
sudo chown gdm:gdm /var/lib/gdm/.pulse/client.conf

增加下面两行:
autospawn = no
daemon-binary = /bin/true

如果还是占用太高,再执行下面这行:
mkdir -p ~/.config/speech-dispatcher && echo “DisableAutoSpawn” >> ~/.config/speech-dispatcher/speechd.conf

ubuntu休眠后无法唤醒黑屏

  1. 检查是否安装了laptop-mode-tools

    dpkg -l | grep laptop-mode-tools
    
  2. 未安装的话,就先安装

    sudo apt-get install laptop-mode-tools
    
  3. 判断Laptop是否启用了laptop_mode模式

    cat /proc/sys/vm/laptop_mode
    

如果显示结果为0,则表示未启动,如果为非0的数字则表示启动了

  1. 启动laptop_mode
    修改配置文件/etc/default/acpi-support,更改ENABLE_LAPTOP_MODE=true。直接在终端中输入sudo laptop_mode start启动了laptop_mode之后,在ubuntu挂起后,基本上就不会遇到无法唤醒的情况了。

如果在/etc/default/acpi-support中未找到ENABLE_LAPTOP_MODE=true被注释的项,看文件最后一行的提示:

# Note: to enable "laptop mode" (to spin down your hard drive for longer
# periods of time), install the laptop-mode-tools package and configure
# it in /etc/laptop-mode/laptop-mode.conf.

打开/etc/laptop-mode/laptop-mode.conf文件,设置以下项

# Enable laptop mode power saving, when on battery power.
#
ENABLE_LAPTOP_MODE_ON_BATTERY=1

#
# Enable laptop mode power savings, even when on AC power.
# This is useful when running as a headless machine, in low power mode
#
ENABLE_LAPTOP_MODE_ON_AC=1

#
# Enable laptop mode when the laptop's lid is closed, even when we're on AC
# power? (ACPI-ONLY)
#
ENABLE_LAPTOP_MODE_WHEN_LID_CLOSED=1

启动laptop_mode并查看结果
sudo laptop_mode start
cat /proc/sys/vm/laptop_mode

ubuntu设置快速启动图标

cd ~/.local/share/applications/

以已有的为基础,复制一个
cp a.desktop b.desktop

然后修改复制出来的文件即可。

tomcat 学习笔记

tomcat 登录用户名 与 密码设置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
403 Access Denied

You are not authorized to view this page.

If you have already configured the Host Manager application to allow access and you have used your browsers back button, used a saved book-mark or similar then you may have triggered the cross-site request forgery (CSRF) protection that has been enabled for the HTML interface of the Host Manager application. You will need to reset this protection by returning to the main Host Manager page. Once you return to this page, you will be able to continue using the Host Manager application's HTML interface normally. If you continue to see this access denied message, check that you have the necessary permissions to access this application.

If you have not changed any configuration files, please examine the file conf/tomcat-users.xml in your installation. That file must contain the credentials to let you use this webapp.

For example, to add the admin-gui role to a user named tomcat with a password of s3cret, add the following to the config file listed above.

<role rolename="admin-gui"/>
<user username="tomcat" password="s3cret" roles="admin-gui"/>

Note that for Tomcat 7 onwards, the roles required to use the host manager application were changed from the single admin role to the following two roles. You will need to assign the role(s) required for the functionality you wish to access.

admin-gui - allows access to the HTML GUI
admin-script - allows access to the text interface
The HTML interface is protected against CSRF but the text interface is not. To maintain the CSRF protection:

Users with the admin-gui role should not be granted the admin-script role.
If the text interface is accessed through a browser (e.g. for testing since this interface is intended for tools not humans) then the browser must be closed afterwards to terminate the session.

Tomcat Manager是Tomcat自带的、用于对Tomcat自身以及部署在Tomcat上的应用进行管理的web应用。
在默认情况下,Tomcat Manager是处于禁用状态的。准确地说,Tomcat Manager需要以用户角色进行
登录并授权才能使用相应的功能,不过Tomcat并没有配置任何默认的用户,因此需要我们进行相应的
用户配置之后才能使用Tomcat Manager。

在使用Tomcat时,我们通过点击 http://localhost:8080/ 下面的【Host Manager】可以管理Tomcat服务器中的web工程;

设置用户名、有密码的方法:

1、登录用户名和密码我们需要在 目录:${TOMCAT_HOME}/conf/tomcat-users.xml 中修改如下配置:

1
2
<role rolename="admin-gui"/>
<user username="tomcat" password="s3cret" roles="admin-gui"/>

2、进入当前目录下的:context.xml 文件,并作如下修改(其实这一步,可以省略的)

1
2
3
4
5
<?xml version="1.0" encoding="UTF-8"?>
<WatchedResource>WEB-INF/web.xml</WatchedResource>
<Manager pathname="/manager" debug="0" privileged="true" docBase="${TOMCAT_HOME}/webapps/manager" />
<Valve className="org.apache.catalina.valves.CometConnectionManagerValve" />
</Context>

完成这两步之后,重启tomcat ,输入刚才设置的用户名和密码,即可登录Tomcat 管理web project

tomcat配置访问项目时不需要加项目名称

访问JAVA WEB项目的时候,需要在地址中添加项目名称,可以去掉项目名称直接访问项目
目前有两种方式:
方式1: 修改${TOMCAT_HOME}/conf目录下的server.xml配置

1
2
3
4
5
6
7
8
<Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true">
<!-- path留空代表访问域名后面不需要带项目的名称 -->
<Context path="" docBase="/home/hewentian/ProjectD/brandSearch" reloadable="true" />
</Host>

说明:
path: 代表访问时的项目名称
docBase: 代表项目的绝对路径,也可以使用相对路径

方式2:将项目下的文件复制放到${TOMCAT_HOME}/webapps/ROOT目录下
所有的项目都在webapps目录里面,ROOT是其中的一个项目,浏览器访问http://localhost:8080/其实是默认访问ROOT项目。

tomcat配置图片目录

修改${TOMCAT_HOME}/conf目录下的server.xml配置

1
2
3
<Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true">
<Context path="img" docBase="/home/hewentian/Pictures" reloadable="false" ></Context>
</Host>

这样当你在浏览器中访问http://localhost:8080/img/{指定图片名}的时候就会访问到/home/hewentian/Pictures目录下面的图片

上线注意事项

今天下午准备上线,折腾了很久,不过,终于成功上线,期间发现了很多问题。所谓好记性,不如烂笔头,故记之。有时候,系统上线,如果发现还是旧的页面,可能会是缓存,这时候,要检查下下面的地方:

  1. 你浏览器的缓存是否已经清掉了;
  2. Tomcat 的缓存是否清掉了${TOMCAT_HOME}/work这个目录,放的就是 Tomcat 的缓存;
  3. 如果 IP + PORT 访问,没问题的话,有可能是 CDN 缓存了,这时候也要刷下 CDN;