在 Linux 下安装字体

Most of computer fonts people using are TrueTpye fonts. TrueType fonts end with .ttf, which stand for TrueType Font. This tutorial shows how to install TrueType fonts in Linux (Debian, Ubuntu, Linux Mint, etc).

Linux 字体文件夹

Linux 下默认安装的字体都被存放在 /usr/share/fonts 下。

如果是个人使用可以将字体文件拷贝到 ~/.fonts 目录中。所有支持的字体文件路径可以通过系统的 /etc/fonts/fonts.conf 文件查看到。

把字体文件拷贝到对应的目录之后,需要执行

# create an index of scalable font files for X
mkfontscale
# create an index of X font files in a directory
mkfontdir
fc-cache -fv

查看已安装字体

使用如下命令来查看已安装字体:

fc-list
# 查看中文字体
fc-list :lang=zh

General way to install TrueType fonts

All of the TrueType fonts are under /usr/share/fonts/truetype, simplest way is to copy ttf file to this directory and give it the right permission. For example, if you want to install Ubuntu font family manually. You can download the font file from official site.

In the terminal, download the package:

 wget http://font.ubuntu.com/download/ubuntu-font-family-0.80.zip

unzip the file into directory ubuntu-font-family-0.80

 unzip ubuntu-font-family-0.80.zip

and then use copy command to copy all the files to /usr/share/fonts/truetype,/usr/share/fonts directory and sub directory need root to write, so you should add sudo before command. The -r paramater represent recursive, it means all the files under ubuntu-font-family-0.80 will be copied to the right place.

 sudo cp -r ubuntu-font-family-0.80/ /usr/share/fonts/truetype/

finally, you shoulde give this directory and all the ttf under this directory right permission. All the new fonts now can only be used by root. We need to change the permission to let all the users to use these fonts:

 sudo chmod 755 /usr/share/fonts/truetype/ubuntu-font-family-0.80/ -R

then, refresh the font cache to let system detect these fonts:

 fc-cache -f -v

Install new fonts only for current user

As I mentioned in the first part, if you copy the ttf file to /usr/share/fonts directory, all the users can use these new fonts. But if you only want to provide these fonts to specific user, like current login user , you can just copy the file to ~/.fonts directory. If there is no such directory, just create it. The ~ stand for current user’s home directory, full path is /home/<username>. So repeat the operation to install Ubuntu font family:

mkdir ~/.fonts
cp -r ubuntu-font-family-0.80/ ~/.fonts/
fc-cache -fv

Install microsoft core fonts

Microsoft Core Fonts include these fonts:

  • Andale Mono
  • Arial Black
  • Arial (Bold, Italic, Bold Italic)
  • Comic Sans MS (Bold)
  • Courier New (Bold, Italic, Bold Italic)
  • Georgia (Bold, Italic, Bold Italic)
  • Impact
  • Times New Roman (Bold, Italic, Bold Italic)
  • Trebuchet (Bold, Italic, Bold Italic)
  • Verdana (Bold, Italic, Bold Italic)
  • Webdings

Debian/Ubuntn/Linux Mint user just open terminal and run these command:

sudo apt-get install ttf-mscorefonts-installer

or Linux Mint user can find this package in the Software Manager, just search it and click install.

Install Chinese fonts

.ttf files are the English fonts, while .TTF files are Chinese fonts. If we check the C:\Windows\Fonts under Microsoft Windows, there are 3 kind of fonts. One is the .fon fonts, which is the DOS system font, and other two fonts are .ttf and .TTF. We can just make a copy of all .ttf and .TTF file and copy all the files to /usr/share/fonts/ directory under Linux. Although it is illegal under Microsoft’s TOC, but we can still do it. :)

If you dual boot your computer, mount the Windows and copy the files

sudo mkdir /usr/share/fonts/truetype/WindowsFonts
sudo cp -r /media/Windows/Fonts/*.ttf /usr/share/fonts/truetype/WindowsFonts/
sudo cp -r /media/Windows/Fonts/*.TTF /usr/share/fonts/truetype/WindowsFonts/

Install open source Chinese fonts, like 文泉驿 - 微米黑 文泉驿 - 正黑

sudo apt-get install ttf-wqy-microhei ttf-wqy-zenhei

several Chinese font we can choose:

To check more about Chinese font visit Arch wiki

Tip

Install Software Manager under Linux Mint

Linux Mint user can find a font manager under Software Manager. It is really a cool tool to manager your fonts.

List all available fonts

fc-list is a quick and handy command to lists fonts and styles available on the system for applications using fontconfig. You can use fc-list to find out whether particular language font is installed or not.

To list all font faces:

$ fc-list

To lists font faces that cover Chinese language:

$ fc-list :lang=zh

Output will be all available Chinese fonts.

Fix WPS for Linux font missing error

After I installed WPS for Linux under Linux Mint 17.2, I met this problem, “系统缺失字体 symbol、wingdings、wingdings 2、wingdings 3、wedding”. According to the copyright, WPS for Linux doesn’t contains these five fonts. You can only find these five fonts and install them in the right place like I said before. One way to find these fonts is to find them in Microsoft Windows system. And another way is to download these files from Internet and install.

Install Korean fonts

Use following command to search Korean font

apt-cache search korean font

and use this command to install Korean font to linux:

sudo apt-get install fonts-unfonts-core fonts-unfonts-extra

常识

字体类型:

  • Sans-serif 无衬线体 = 黑体:并不是具体一款字体,而是一类字体,选择它其实等于选择这类字体中优先级最高的那款字体。
  • Serif 衬线体 = 白体:同上
  • Monospace 等宽字体,意思是字符宽度相同:同上
  • 点阵字体 位图字体

无衬线体更适合电脑屏幕阅读,衬线体适合打印。因为衬线可以使得人视线平齐于一行。也就是说不会读破行。

中文显示时有不同的方式,一方面因为中文本身拥有的横和同高度就可以导致这种平齐。行距对中文更重要。

For more information check Debian page Arch wiki and Ubuntu wiki


2015-10-21 linux , linux-mint , fonts , font , truetype

git presentation

之前做过一个简单的 git 的介绍,下面是 PPT 的摘录。

What is Git

Git is a free and open source distributed version control system(VCS) designed to handle everything from small to very large projects with speed and efficiency.

Git 是一个分散式版本控制软件,最初由林纳斯·托瓦兹(Linus Torvalds)创作,于 2005 年以 GPL 发布。最初目的是为更好地管理 Linux 内核开发而设计。Linus Torvalds 自嘲的取名“git”,该词源自英国俚语,意思大约是“混账 1”。

版本控制系统

Version Control Example

Microsoft Word 如果你用 Microsoft Word 写过长篇大论,那你一定有这样的经历:

想删除一个段落,又怕将来想恢复找不回来怎么办?有办法,先把当前文件“另存为……”一个新的 Word 文件,再接着改,改到一定程度,再“另存为……”一个新文件,这样一直改下去,最后你的 Word 文档变成了这样:

Wikis

https://zh.wikipedia.org/w/index.php?title=Git&action=history

Undo Windows: Ctrl+z Mac: Command+z

History

Version control has a very long histroy.

  • Source Code Control System (SCCS)
  • 1972, closed source, free with Unix
  • Revision Control System (RCS)
  • 1982, open source
  • Concurrent Versions System (CVS)
  • 1986-1990, open source
  • Apache Subversion (SVN)
  • 2000, open source

BitKeeper SCM

  • 2000, closed source, proprietary
  • distributed version control
  • “community version” was free
  • used for source code of the Linux kernel from 2002-2005
  • Controversial to use proprietary SCM for an open source project
  • April 2005: the “community version” not free anymore

Git is born

  • April 2005
  • created by Linus Torvalds
  • replacement for BitKeeper to manager Linux kernel source code
  • distributed version control
  • open source and free software
  • compatible with Unix-like systems (Linux, Mac OS X, and Solaris) and Windows
  • faster than other SCMs (100x in some cases)

Git become popular, GitHub launched in 2008 to host Git repositories:

  • 2009: over 50,000 repositories, over 100,000 users
  • 2011: over 2 million repositories, over 1 million users

分布式

Git 是一种分布式版本控制,不需要服务器端软件也可运行

  • 不同用户维护自己的版本库,而不是和核心版本库交换数据
  • 追踪 “change sets” 或者 ”patches”
  • 无需网络,随时随地进行版本控制
  • 分支的新建、合并非常方便、快速,没有任何成本,基本不耗时

Who use Git?

anyone wanting to track edits

  • review a histroy log of changes made
  • view differences between versions
  • retrieve old versions

anyone needing to share changes with collaborators

anyone not afraid of command-line tools

需要注意以下几点:

  1. 只能跟踪文本文件的改动,二进制文件不行,也就是说 如果使用 Git 追踪 Word ,版本控制系统并不知道改动了那些行,只能知道二进制变化了。

    programmer

    • HTML, CSS, JavaScript
    • PHP, Ruby, Ruby on Rails, Perl, Python, ASP
    • Java, C, C++, C#, Objective-C
    • ActionScript, CoffeeScript, Haskell, Scala, Shell scripts

    not as useful for tracking non-text files

    • images, movies, music, fonts
    • word processing files, spreadsheets, PDFs
  2. 编码问题,如果在多平台使用请千万使用 UTF-8 编码

    使用 Windows 的童鞋要特别注意: 千万不要使用 Windows 自带的记事本编辑任何⽂文本⽂文件。原因是 Microsoft 开发记事本的团 队使⽤用了⼀一 个非常弱智的⾏行为来保存 UTF-8 编码的⽂文件,他们⾃自作聪明地在每个⽂文件开头添 加了 0xefbbbf(⼗十六进制)的字符,你会遇到很多不可思议的问题,比 如,网页第一⾏行可 能会显⽰示⼀一个“?”,明明正确的程序⼀一编译就报语法错误,等等,都是由记事本的弱智⾏行 为带来的。建议你下载 Notepad++ 代替记事本,不但功能强⼤大,而且免费!记得把 Notepad++ 的默认编码设置为 UTF-8 without BOM 即可

install

  • Linux

sudo apt-get install git or sudo yum install git

  • mac

brew install git

  • windows

https://git-scm.com/

Git basic

在开始使用 Git 之前有些配置

git config --global user.name "John Doe"  # 配置提交用户名
git config --global user.email johndoe@example.com  # 配置提交邮箱


git init
git status
git add filename
# 暂存区
git commit -m “"
git log

commit message best practices

  • short single-line summary ( less then 50 characters 或者 小于 25 个汉字)
  • optionally followed by a blank line and a more complete description
  • keep each line to less than 72 characters
  • write commit messages in present tense, not past tense
    • “fix bug” or “fixes bug”, not “fixed bug”

branch

git branch <branchname>
git checkout <branchname>
git checkout -b <branchname>

git push origin <branchname>

git push origin --delete <branchname>

http://nvie.com/posts/a-successful-git-branching-model/

remote

git remote add origin git@blcu.tk:einverne/gitdemo.git
git push -u origin master
git remote show origin

tag

git tag     # list all tags
git tag v0.9
git tag -a v1.0 -m “my version 1.0"
git show tag name #show tag details
git push origin tag name
git push origin --tags

git GUI

other

gitignore

https://github.com/github/gitignore

alias

git config --global alias.st status
git config --global alias.co checkout
git config --global alias.ci commit
git config --global alias.br branch
git config --global alias.unstage 'reset HEAD --'
git config --global alias.last 'log -1 HEAD'

GitLab server

http://server.address
  1. http://git.or.cz/gitwiki/GitFaq#head-90fa13ebe170116f1586156e73b549cc2135b784 


2015-10-12 git , linux , version-control

Java 中时间相关处理工具类库 joda time

注意如果使用 Java SE 8 及以上,建议使用 java.time (JSR-210) 来代替使用 Joda-time。

Java 中日期,时间处理类库 Joda time

依赖

<dependency>
    <groupId>joda-time</groupId>
    <artifactId>joda-time</artifactId>
    <version>2.10.2</version>
</dependency>

最新的版本官网查看 1

使用

5 个最常用的 date-time 类:

  • Instant - Immutable Class,用来表示时间轴上一个瞬时的点
  • DateTime - Immutable Class,用来替换 JDK 的 Calendar 类
  • LocalDate - Immutable Class,表示一个本地的日期,而不包含时间部分(没有时区信息), 适合表示出生日期
  • LocalTime - Immutable Class,表示一个本地的时间,而不包含日期部分(没有时区信息), 适合表示商店的每天开门 / 关门时间
  • LocalDateTime - Immutable Class,表示一个本地的日期-时间(没有时区信息)

Instant

表示时刻,瞬时的时间

Interval

表示时间间隔,是一个半开区间,包括开始时刻,但不包括结束时刻。结束时刻永远要大于或者等于开始时刻。有两个实现 Interval 和 MutableInterval

Duration

表示持续时间,用 milliseconds 表示,duration 通常从 interval 中获取。

instant  +  duration  =  instant

Period

一段时间,通常比如三年五个月两天 7 小时。他和 Duration 的区别在于,Period 是不精确的(在 milliseconds 级别)。比如有一个月的时间段,那么在二月一号加上一个月会得到三月一号,而在三月一号加上一个月,会得到四月一号,但是这两个 duration(in milliseconds)是完全不一样的。

instant  +  period  =  instant

有两个实现 Period 和 MutablePeriod

DateTime

有很多构造方法

DateTime dateTime1 = new DateTime();
DateTime dateTime2 = new DateTime(2015,11,11,0,0,0);
DateTime dateTime3 = new DateTime(1447171200000L);
DateTime dateTime4 = new DateTime(new Date());
DateTime dateTime5 = new DateTime("2015-11-11T00:00:00.000+08:00");

LocalTime

Joda Time 中的 LocalTime 表示的是一个没有日期的时间

常用方法

LocalTime.now()

Interval 和 Period

Joda-Time 为时间段的表示提供了支持。

  • Interval:保存了一个开始时刻和一个结束时刻,因此能够表示一段时间,并进行这段时间的相应操作
  • Period:保存了一段时间,比如:6 个月,3 天,7 小时这样的概念。可以直接创建 Period,或者从 Interval 对象构建。
  • Duration:保存了一个精确的毫秒数。同样地,可以直接创建 Duration,也可以从 Interval 对象构建。

JDK8 中的时间相关

因为 Joda Time 非常稳定可靠,在 JDK 8 以前成为了 Java 处理时间相关的事实标准,JDK 8 中引入了 java.time 等一组新 api 用来处理时间日期,遵守 JSR 310,弥补了 Java 在时间处理方面的不足。Joda-Time 的作者 Stephen Colebourne 和 Oracle 一起共同参与了这些 API 的设计和实现。

JDK 8 以前 Date 和 Calendar 类存在的问题:

  • 非线程安全,需要额外的代码来处理线程安全问题
  • 接口设计,之前的接口处理 day-to-day 操作困难
  • 时区相关时间,需要额外处理

相关类:

  • Instant 时刻
  • Duration
  • LocalDate 日期,2015-01-01
  • LocalTime 时间
  • LocalDateTime 日期和时间 2015-01-01T14:02:43.455

基本上他们的接口定义都是 ofXX 来构造一个实例,而通过 parseXX 来将一个现有的时间戳转变成对应的实例。

reference

  1. https://mvnrepository.com/artifact/joda-time/joda-time 


2015-10-11 java , joda-time , jdk8

wget 常用命令

wget 是一个非常常用的下载命令,但其实 wget 非常强大,这里就列举一些很常用的选项。

下载整站

备份或者下载整站:

wget -r -np http://www.mysite.com/Pictures/
wget -r --no-parent --reject "index.html*" http://www.mysite.com/Pictures/

说明:

  • -r 表示 recursively 递归下载
  • -np 或者 --no-parent 表示不延伸到父目录,当想要下载特定目录下的文件时,记得加上这个选项

当然如果你的目的非常单纯只是想备份网站,之前也写过一篇 Httrack 备份全站 的文章。

下载特定文件或者忽略特定文件

使用 -A 或者 -R

wget -A jpg,pdf http://site
wget --accept jpg,pdf http://site

wget -R "index.html" http://site

说明:

  • -A 或者 --accept 后面接逗号分割的后缀或者模式,表示下载接受的文件格式,或者符合正则表达式的内容
  • -R 或者 --reject 表示不下载匹配的

需要注意的是如果书写正则表达式,那么需要用双引号。

路径乱码

在使用 wget 备份网站目录时可能遇到网站路径编码下载到本地之后乱码的情况,这个时候需要使用 --restrict-file-names=nocontrol

镜像网站

有些时候可能要离线文档用来在本地浏览,这个时候需要用到 -k

wget --mirror --convert-links --adjust-extension --page-requisites
--no-parent http://example.org
wget -mkEpnp http://example.org

说明:

  • -m 或者 --mirror 镜像网站,这个选项会开启递归和时间戳,并且保持目录结构,等效于 -r -N -l inf --no-remove-listing
  • -k 或者 --convert-links 表示将连接转成 localhost,方便本地浏览
  • -E 或者 --adjust-extension 表示会根据文件的 MIME 类型,将一些文件调整为 HTML 等等后缀,方便在不同的 WEB 服务器中托管
  • -p 或者 --page-requisites 会将任何 HTML 页面显示需要的资源都下载下来,包括 images,sounds,css,js 等等

限制网速

wget 使用选项 --limit-rate 来限制速度:

wget --limit-rate=423k

单位是 bytes per second,如果要表示 kiloBytes,在结尾加上 k .

自定义重试次数

使用 --tries=70 来自定义重试次数,默认情况下 wget 会重试 20 次。


2015-10-03 wget , curl , linux , linux-command , backup

残忍的战争

接触韩国电影并不是很长时间,而之前在我看过的电影中推荐过《10部不得不看的韩国电影》,这之后通过周围的推荐和影评,渐渐的看到了更多的韩国电影。《追击者》《太极旗飘扬》《汉江怪物》,这些都是非常不错的片子,可惜当时并不知道。而这部《太极旗飘扬》终于在昨天看完了。

如何去定义这部电影呢?战争片,历史片,影片主要讲述朝鲜战争,也就是韩国说的6.25战争,兄弟俩被强制征兵到前线抵抗北朝鲜的进攻,而哥哥为了保护弟弟屡次铤而走险,完成战功,获得勋章,而过程中哥哥却变的残暴。故事中的哥哥多次的反转,或许这里真的要称赞一下电影的编剧,从来没想到故事的发展会如此的曲折,而最后终也能将电影所要衬托出的主题凸显出—-这是一部彻彻底底的反战电影—-就像之前看的一篇影评中所说,历史上的朝鲜战争,在世界各国的书本中都描述成中国,前苏联和美国的势力角逐。而这部电影让我们看到韩国人对这次战争的思考,当世界两大力量在小小的朝鲜半岛展开时,血腥,暴力是无法想象的,而导演也同样没有回避,用大量的镜头描写战争场面的残酷。

太极旗飘扬

作为一个中国人来看,或许很多人的印象中都是“雄赳赳气昂昂,踏过鸭绿江”,我们的教科书,我们的老师,我们的教育从来没有教育我们战争对于人类来说是什么。多少次观影的过程中,我希望中国从来没有参战,没有之后的更加疯狂的杀戮,也同样不会有那些年战死的中国志愿军。而历史就是历史,一直知道中国会参战,而当韩国军队获得胜利朝鸭绿江挺近的时候,我依然会和主人公一样的开心。这是一部很长的电影,长得让人难受的电影,导演用镜头诉说着那段历史,一个个的反转让人思考。

其中最大的反转就是哥哥这个角色,最开始哥哥弟弟并不愿意参战,而后来哥哥为了弟弟变得疯狂,看到北朝鲜屠杀村民,哥哥变得嗜血,屠戮战俘,哥哥甚至为了功勋而忘记了初心,勋章荣誉让哥哥沉迷其中,成为战争英雄。而之后哥哥看到自己的未婚妻因为战时投奔共产党讨得一点饭吃而被韩国同胞处死,而自己的弟弟被关在仓库烧死(哥哥并不知道弟弟侥幸逃走),从而变得更加疯狂,被北朝鲜俘虏之后成为了北朝鲜的主力“大旗部队”,哥哥的一生,为自己的弟弟,为自己的国家战斗过,也为北朝鲜战斗过,他甚至并不知道为什么要打来打去,莫名其妙的被拉上战场,而之后的一切都被动的产生了。导演很聪明,没有直接明了的说道理,去站在上帝的视角去评价这场战争,同样也很聪明的屏蔽了外界的一切的干扰,中国志愿军只出现了一幕,而美国军队的登陆也只是在收音机中出现,所有的镜头都是正面的战场,保留了观众对这场战争的评价,是非曲直,看完的观众心中自有一个定论。

而弟弟的表现则告诉我们,一个人保留有一丝的人性是多么的重要,即使战争再残酷,人作为人最基本的人性应该保存着,这也就是他即使再忙也会跑到家里去看望自己的母亲和嫂嫂,这也就是他即使所有人都认为那个投降朝鲜的天真擦皮鞋的老乡该杀的时候他会跑出来保护他,这也就是他即使知道前线的危险也会再跑到战场去寻找他的哥哥的原因。人作为人,是应该像哥哥那样,还是像弟弟那样?就像电影中弟弟告诉他哥哥的那样,“如果把那些战俘都杀死,那我们和那些北朝鲜的人又有什么两样?”。

很多人提到这部片子会想到另外一部战争大片《拯救大兵瑞恩》,有的时候我真的会问自己,“为了一个人,又牺牲了那么多的人,真的值得吗?”,我的回答肯定是“值!”,因为这里面就包含着人对生命的尊敬,对战争的敬畏,我相信看完这些电影的人一定是反战的,战争是反人类的。说到底战争只是政府政治斗争的一枚棋子,而受到伤害的永远都是社会底层的平民。

PS.

写完本来是要分享到豆瓣的,只是又不过审了。


2015-09-27 影评 , 韩国

Bash 学习笔记之基本使用

Bash 的前身 shell 是 Unix 系统下的命令行解释器,主要用于用户和系统交互。 Unix 系统上有很多 Shell,首个 Shell,Bourne Shell,1978 年推出,后来又演变出 C Shell,Bash 等不同版本的 Shell。

Bash 全称为 Bourne-Again Shell,是一个为 GNU 项目编写的的 Unix Shell。Bash 脚本功能强大,尤其是在处理循环或者批量任务时。Bash 是大多数 Linux 平台默认的 Shell,所以学好 Bash 是基础。

首选来看一下 Bash 的版本,输入下面命令

echo $BASH_VERSION

命令行编辑 Emacs mode vs Vi Mode

可以使用 set -o | egrep -w "(vi|emacs)" 命令查看,当前命令行编辑模式。

$ set -o vi
$ set -o|egrep -w "(vi|emacs)"
emacs           off
vi              on

All the above assume that bash is running in the default Emacs setting, if you prefer this can be switched to Vi shortcuts instead.

Set Vi Mode in bash:

$ set -o vi

Set Emacs Mode in bash:

$ set -o emacs

using set -o to check all the bash options.

Emacs 编辑模式

完整 Emacs 编辑模式快捷键,文档 link

Bash Keyboard Shortcuts 在绝大多数情况下一下快捷键可以直接使用

移动光标 Moving the cursor

在终端移动快捷键,下面几个快捷键在命令行中非常有用,尤其是当命令比较长时,在行前,行末快速切换能够提高不少效率。而如果要修改命令行中间内容,这时候组合使用 alt ctrl 和 b f 则能够快速定位到中间修改的内容,再进行修改。

Command Explain
Ctrl + a 移动到命令最前 Go to the beginning of the line (Home)
Ctrl + e 移动到行尾 Go to the End of the line (End)
Ctrl + p 上一个命令 Previous command (Up arrow)
Ctrl + n 下一个命令 Next command (Down arrow)
Alt + b 不删除命令的情况下,向前移动一个单词 Back (left) one word
Alt + f 向后一个单词 Forward (right) one word
Ctrl + b 光标向前移动一个字符 Backward
Ctrl + f 光标向后移动一个字符 Forward
Ctrl + xx 在行首和当前光标的位置来回切换 Toggle between the start of line and current cursor position

Ctrl-bCtrl-f 这两个快捷键是我经常容易忘记的两个,但是有的时候又要比左右方向键要方便很多,所以还是要记一下的。

编辑 Editing

编辑相关的快捷键,对我而言 Ctrl + w 是一个非常常用的快捷键,当输入发生错误时,直接快速删除前一个单词再进行修正。

Command Explain
Ctrl + L Clear the Screen, similar to the clear command
Alt + Del Delete the Word before the cursor.
Alt + d Delete the Word after the cursor.
Ctrl + d Delete character under the cursor
Ctrl + h Delete character before the cursor (Backspace)
Ctrl + w Cut the Word before the cursor to the clipboard. 一般用来快速删除前一个单词,也可以用 Alt + Backspace
Ctrl + k Cut the Line after the cursor to the clipboard. 将光标后面的内容剪切
Ctrl + u Cut/delete the Line before the cursor to the clipboard. 一般用来快速清除当前输入命令
Alt + t Swap current word with previous
Ctrl + t Swap the last two characters before the cursor (typo).
Esc + t Swap the last two words before the cursor.
Ctrl + y Paste the last thing to be cut (yank)
Alt + u UPPER capitalize every character from the cursor to the end of the current word.
Alt + l Lower the case of every character from the cursor to the end of the current word.
Alt + c Capitalize the character under the cursor and move to the end of the word.
Alt + r Cancel the changes and put back the line as it was in the history (revert).
Ctrl + _ Undo
TAB Tab completion for file/directory names

For example, to move to a directory ‘sample1’; Type cd sam ; then press TAB and ENTER. type just enough characters to uniquely identify the directory you wish to open.

历史 History

查询 bash 命令历史,快速执行历史命令

Command Explain
Ctrl + r Recall the last command including the specified character(s)
searches the command history as you type.
Equivalent to : vim ~/.bash_history.
Ctrl + p Previous command in history (i.e. walk back through the command history)
Ctrl + n Next command in history (i.e. walk forward through the command history)
Ctrl + s Go back to the next most recent command.
(beware to not execute it from a terminal because this will also launch its XOFF).
Ctrl + o Execute the command found via Ctrl+r or Ctrl+s
Ctrl + g Escape from history searching mode
!! Repeat last command
!abc Run last command starting with abc
!abc:p Print last command starting with abc
!$ Last argument of previous command
ALT + . Last argument of previous command
!* All arguments of previous command
^abc­^­def Run previous command, replacing abc with def

进程控制 Process control

下面几个命令可以控制命令行中正在执行的进程,包括中止进程,放置进程到后台,唤起进程等等。

Command Explain
Ctrl + C Interrupt/Kill whatever you are running (SIGINT)
Ctrl + s Stop output to the screen (for long running verbose commands)
  Then use PgUp/PgDn for navigation
Ctrl + q Allow output to the screen (if previously stopped using command above)
Ctrl + D 退出当前 Shell Send an EOF marker, unless disabled by an option, this will close the current shell (EXIT)
Ctrl + Z Send the signal SIGTSTP to the current task, which suspends it.
To return to it later enter fg ‘process name’ (foreground).

最常使用的应该还是 Ctrl-a, Ctrl-e, Ctrl-f, Ctrl-b, Ctrl-l, Ctrl-h, Ctrl-w, Ctrl-k, Ctrl-u, Ctrl-y, Ctrl-r.

命令 说明
Ctrl-B 后移一个字符
Ctrl-F 向前移动一个字符
DEL 向后删除一个字符
Ctrl-D 向前删除一个字符
Ctrl-A 移到行首
Ctrl-E 移到行尾
Ctrl-K 向前删除到行尾
Ctrl-P 移到前一行
Ctrl-N 移到后一行
Ctrl-R 向后搜索
Ctrl-J 等同于 RETURN
Ctrl-L 清除屏幕,将当前行放到屏幕最上面
Ctrl-M 等同于 RETURN
Ctrl-O 等同于 RETURN 随后在显示历史命令中下一行
Ctrl-T 颠倒光标左右两个字符,将光标向前移一个
Ctrl-U 从光标位置开始删除行 ,向后删除到行首
Ctrl-V 引用插入

Vi 编辑模式

通过设置 set -o vi 进入 Vi 编辑模式,正常环境为输入模式,对命令进行修改则按 Esc。完整命令参考.

命令包括 h, l, w, b 等等 Vi 中使用的命令,可参考另外一篇 Vim 学习笔记

  • 通过按键 Esc , Ctrl+l(L lower case) ,clear screen。
  • Ctrl-w
  • Ctrl-u
  • Ctrl-k
  • Ctrl-y
  • Ctrl-r

环境配置

特殊文件

最重要的 Bash 文件是 .bash_profile ,它在每次用户登陆系统时被读取 /etc/profile 。Bash 允许有 .bash_profile 两个同义文件, C Shell 的 .bash_login 以及 Bourne Shell 和 Korn Shell 的 .profile 。登录时三者中只有一个被读取,如果用户根目录下 .bash_profile 不存在,则 bash 依次查找 .bash_login , .profile.

.bash_profile 只被登录 shell 读取并执行,如果通过命令键入 Bash 启动一个新 Shell, 它就会读取 bashrc 中的命令。

.bash_logout 在每次 shell 退出时被读取并执行。

可以使用 source ~/.bashrc 来使配置文件立即生效。

修改 .bashrc 文件可以精确到对当前用户有效。修改 /etc/profile 对全局用户生效。

别名

给命令添加熟悉的别名

alias name=command

指定 name 是 command 的别名。在“=”两边没有空格,严格语法。

别名是可递归的,可以使用别名定义另外的别名。

选项

别名可以为命令创建方便的名字,它们实际上并不改变 shell 的行为。选项则不然。基本命令:

set -o optionname	- 号 开启
set +o optionname	+ 号 关闭

检查 bash 所有可选项,使用 set -o 打印所有列表。

shopt 选项

选项 含义
-p 显示可选设置及其当前取值
-s 设置
-u 失效
-o 允许选项名取值通过 set 命令 -o 选项定义

列表选项如下:

allexport           off
braceexpand         on
emacs               off
errexit             off
errtrace            off
functrace           off
hashall             on
histexpand          on
history             on
ignoreeof           off
interactive-comments     on
keyword             off
monitor             on
noclobber           on
noexec              off
noglob              off
nolog               off
notify              off
nounset             off
onecmd              off
physical            off
pipefail            off
posix               off
privileged          off
verbose             off
vi                  on
xtrace              off
选项 解释
emacs emacs 编辑模式
vi vi 编辑模式
ignoreeof 不允许单独使用 Ctrl-D 退出
noclobber 不允许输出重定向(>)覆盖已存在的文件
noglob 不允许扩展文件名通配符如*和?
nounset 试图使用未定义变量时给出错误

变量

Shell 变量也是一个拥有取值的名字,bash 有一些内置的变量,shell 编程也可以自定义变量。按照惯例,内置变量名均为大写,当然也有两个例外。

varname=value

等号两边必须没有空格

引用变量,使用符号 $ , 单引号内部的变量会直接使用而不需要转义,而双引号内部变量需要转义

echo $varname

bash 有很多内置变量分布在各个配置文件中。

内置变量

PATH 变量,帮助 shell 找到输入的命令。输入 echo $PATH 得到类似:

/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
变量 含义
HOME 主目录
SECONDS 调用 shell 的秒数
BASH 正在运行的 shell 实例路径名
BASH_VERSION shell 版本号
BASH_VERSINFO shell 版本信息数组
PWD 当前目录
OLDPWD 最后一个 cd 命令前的目录

2015-09-26 linux , bash , vim , shell , zsh , unix , command , cli

Linux 学习笔记 User and Group

Linux 是一个多用户、多任务的操作系统,所以为了运行这样一套系统,必须要有一套用户管理系统。

User

root 用户是所有类 Unix 系统中的超级管理员,UID 是 0。

/etc/passwd

类似如下:

root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/bin/sh
bin:x:2:2:bin:/bin:/bin/sh

7 个部分:

  • 账户名称
  • 密码,已被移到 /etc/shadow 目录中
  • UID - 0 代表“系统管理员” - 1~499 保留系统使用,1~99 保留系统默认帐号,另外 100~499 则保留给服务使用 - 500~65535 一般用户使用,Linux 2.6.x 已经可以支持 2 的 32 次方减 1 UID
  • GID
  • 用户信息说明
  • home dir
  • shell

UID 是不能有冲突的,并且普通用户必须从 1000 开始,即使前面有空缺。

/etc/shadow

加密的密码

9 个部分:

  • 帐号名称
  • 密码,加密过,如果为* 或 ! 则表示这个帐号并不会用来登陆
  • 最近更改密码日期,1970 年 1 月 1 号作为 1
  • 密码不可更改天数
  • 密码需要重新更改天数
  • 密码更改期限前的警告期限
  • 密码过期的宽限时间
  • 帐号失效日期
  • 保留

useradd

增加用户

root@linux ~#  useradd username

可以通过 id username 来查看用户的具体资料

/etc/default/useradd

新增用户模板

GROUP=100 #默认用户组 HOME=/home #默认 Home 目录 INACTIVE=-1 # /etc/shadow 内第 7 栏 EXPIRE= # /etc/shadow 内第 8 栏 SHELL=/bin/bash #默认 shell SKEL=/etc/skel #home 目录内容数据参考

/etc/skel/*

新增用户 home 目录参考

passwd

设置密码,直接 passwd 则是修改自己密码

root@Linux ~# passwd username

usermod

调整用户帐户信息

userdel

删除用户

root@linux /# userdel [-r] username

-r 连同 home 目录一起删除

Group

为了管理一组用户,Linux 系统中有组概念,通过用户组 GID, 来区别。

/etc/group

类似

root:x:0:root
daemon:x:1:root,bin,daemon
bin:x:2:root,bin,daemon
sys:x:3:root,bin,adm

4 部分:

  • 用户组名称
  • 用户组密码 /etc/gshadow
  • GID
  • 支持的帐号名称

####有效用户组 查看已 einverne 用户身份登录,支持的用户组命令:

pi@linux / $ groups
pi adm dialout cdrom sudo audio video plugdev games users netdev gpio i2c spi input

使用命令 newgrp groupname 切换有效用户

/etc/gshadow

类似:

root:::root

4 个字段:

  • 用户组名称
  • 密码栏,以 ! 开头表示无法登陆
  • 用户组管理员帐号
  • 用户组所属帐号

groupadd

命令:

root@linux ~# groupadd groupname

groupmod

调整 group 相关参数

root@linux ~# groupmod -g 103 -n groupname groupothername

groupdel

删除用户组

root@linux ~# groupdel groupname

su & sudo

/etc/sudoers 文件,建议使用 visudo 编辑该文件

格式:用户帐号 登录主机 = (可变换的身份) 可执行的命令

用户 einverne ALL = (ALL) ALL 用户组内 %groupname ALL = (ALL) ALL 不需要密码 %groupname ALL = (ALL) NOPASSWD: ALL

chgrp

change file group

chgrp users dirname/filename [-R]

chown [-R]

chown change file owner

chown root:root filename

chmod

change file property, SUID

  • number

      r:4
      w:2
      x:1
    

    chmod [-R] xyz filename/dir

  • 符号

  • 加入 - 除去 = 设置 u user g group o others a all


2015-09-24 linux , user , group , acl , uid , root

Java collections

Collection 是接口,包含 List 和 Set 。List 有序,Set 无序不允许重复元素。

  • List 实现类有 LinkedList, ArrayList, Vector, Stack
  • Set 的实现类 HashSet, TreeSet。HashSet 依赖 HashMap,TreeSet 依赖 TreeMap。

List

List 接口下主要实现

ArrayList

动态数组,继承 AbstractList 实现了 List,RandomAccess,Cloneable, Serializable 等接口。

线程不安全,多线程使用 Vector 或者 CopyOnWriterArrayList

源码解读 基于 jdk 1.8

  • ArrayList 实际是通过数组来保存元素,构造时默认大小为 10,可设定
  • 当 ArrayList 容量不足时,ArrayList 会重新设置容量 int newCapacity = oldCapacity + (oldCapacity >> 1);
  • ArrayList 实现了 Cloneable 接口,意味着可以使用 .clone() 方法来创建全新 ArrayList
  • modCount 用来记录 List 被修改的次数,被 Iterator 使用,可以用来实现 fail-fast 异常,ArrayList 在修改时都会改动 modCount 值,该异常会在多线程中在一个线程中访问数组,另一个线程修改数组时抛出异常

LinkedList

LinkedList 双向链表,继承自 AbstractSequentialList,可以被当做堆栈,队列,双端队列,实现了 List,Deque,Cloneable,Serializable 等接口。

非线程安全

源码解读 jdk 1.8

  • 内部 Node 类,包含着要保存的元素,prev 和 next 指针
  • LinkedList 中重要的成员变量,first,last 和 size,first 和 last 分别表示链表的头和尾,size 是链表的长度
  • LinkedList 既然是链表,所以顺序访问会高效,反而随机访问效率降低,LinkedList 的 get 等根据索引来获取的方法,通过比较 index 和链表长度的一半比较,如果一半前则从头开始找,而一半后则从尾巴开始找
  • LinkedList 可以作为 FIFO,FILO 来使用

Vector

Vector 继承 AbstractList,实现了 RandomAccess,Cloneable, Serializable 接口,是一个列表。

线程安全。

  • 和 ArrayList 一样,默认的长度是 10
  • 重要的成员变量 elementData, elementCount, capacityIncrement
  • Vector 的线程安全使用过 synchronized 关键字来实现的,比如说

    public synchronized boolean add(E e) { modCount++; ensureCapacityHelper(elementCount + 1); elementData[elementCount++] = e; return true; }

总结

  • 多线程中操作数组使用 Vector
  • 如果要快速随机访问应该选择 ArrayList
  • 如果要快速插入和删除 LinkedList

Map

Map 是一个键值对映射接口,Map 不能包含重复键。

HashMap

HashMap 继承自 AbstractMap 实现了 Map<K,V>, Cloneable, Serializable 接口。线程不安全。

HashMap 类有两个参数影响其性能:“初始容量” 和 “加载因子”。容量是哈希表中桶的数量,初始容量 只是哈希表在创建时的容量。加载因子是哈希表在其容量自动增加之前可以达到多满的一种尺度。

HashMap 中 key-value 的值都存在 Entry 的数组中 (Java 8 中 Node 结构)。

transient Node<K,V>[] table;

说到 HashMap,都知道 Java 中每一个 Object 都有一个 hashCode() 方法,该方法返回一个 int 值,相同的对象必须返回相同的 hash Code(不同的对象不一定要求返回不同的值). 在 HashMap 中 hashCode() 方法首先被用来计算 bucket 然后计算 index。

Buckets

Buckets 是 HashMap 中的一个数组元素,它用来保存节点,节点可能有相同的 bucket。Buckets 的容量是不同的,bucket 的容量大致:

capacity = number of buckets * load factor

单一的一个 bucket 可以拥有超过一个 nodes,hashCode() 方法越好,那么 bucket 会利用的更好。

HashMap 中的 Index 计算

HashCode 会产生一组 int 数值,如果我们创建一个这个范围的数组,极有可能造成 outOfMemoryException。所以需要知道产生数组的一个最小大小:

index = hashCode(key) & (n-1)

n 是 bucket 的数值。

重要的成员变量:

  • table 是一个 Entry[] 数组,单向链表
  • size 是 HashMap 大小,保存键值对数目
  • threshold 是阈值,判断是否需要调整容量,threshold= 容量*加载因子,当存储容量达到阈值,需要将 HashMap 容量加倍
  • loadFactor 加载因子
  • modCount 用来实现 fail-fast 机制
  • entrySet 键值对 Set

在上面的描述中,我们知道如果发生 hash 冲突,所有的节点都保存在一个 linked-list 中,那么最坏的时间复杂度可能是 O(n).

为了解决这个问题,Java 8 中 hash 元素当达到一个阈值之后使用了 balanced trees 而不是 linked list. 这意味着 HashMap 在达到一定数量之后将 Entry 对象转而存储到 balanced tree 中,而最坏的时间复杂度从 O(n) 降至 O(log n)

注意点

  • 直到 rehash 之前 put 和 get 的复杂度都是稳定的
  • 假设产生冲突,第二个节点会用 linked list 串起来
  • key 为 null 时 hash code 为 0

Java 8 中的 hash() 方法:

static final int hash(Object key) {
    int h;
    return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}

为了解决哈希碰撞,将 put 到 HashMap 的 key 的 hashCode() 高位和地位综合考虑,在计算时亦或一下高低位(高 16 位异或低 16 位)。

Hashtable

Hashtable 继承 Dictionary,实现 Map, Cloneable, Serializable 接口。Hashtable 函数都是同步的线程安全的,key 和 value 都不能为 null。

Hashtable 和 HashMap 一样,也是通过“拉链法”来实现的。

TreeMap

TreeMap 是一个有序的 key-value 集合,顺序通过 key 排列,通过红黑树实现

public class TreeMap<K,V>
    extends AbstractMap<K,V>
    implements NavigableMap<K,V>, Cloneable, java.io.Serializable

内部根据 key 的自然顺序排序,或者根据创建时提供的 Comparator 排序。基本操作包括 containsKey, get, put, remove 的时间复杂度是 log(n).

TreeMap 不是线程安全的。

内部 Entry 结构包含红黑树节点的 6 个组成部分

static final class Entry<K,V> implements Map.Entry<K,V> {
    K key;
    V value;
    Entry<K,V> left;
    Entry<K,V> right;
    Entry<K,V> parent;
    boolean color = BLACK;

WeakHashMap

WeakHashMap 是弱键,当某个键不再正常使用时会被从 WeakHashMap 中自动移除。准确的来说,对于一个给定的键,并不能阻止垃圾回收器对该键的回收。

WeakHashMap 的 key 是弱键,通过 WeakReference 类型实现。

ReferenceQueue 是一个队列,保存被 GC 回收的弱键。

WeakHashMap 是不同步的,可以使用 Collections.synchronizedMap 来构造同步的 WeakHashMap。

Java 中的引用方式

在理解 WeakHashMap 之前首先要知道 Java 中的几种引用,Strong,Soft,和 Weak 引用。

强引用

Integer one = 1;

GC 不会随意回收强引用

软引用

Integer prime = 1;
SoftReference<Integer> soft = new SoftReference<Integer>(prime);
prime = null;

GC 只有在 JVM 及需内存时才会回收软引用

弱引用

Integer prime = 1;
WeakReference<Integer> soft = new WeakReference<Integer>(prime);
prime = null;

GC 会频繁的回收弱引用内存,即使不是极其需要内存也会进行回收。

WeakHashMap 中就是用了 WeakReference 类型。

使用场景

比如某些情况下需要在 value 中保存极大的内容,比如图片内容,那么会消耗极大的内存,而如果使用普通 HashMap 那么这些图片的内容不会轻易释放,这个时候就使用 WeakHashMap 比较合适。

hash 函数

hash 函数的目的是为了让 key 的 hash 尽量均匀的分布到 bucket 中

final int hash(Object k) {
  int h = k.hashCode();

  h ^= (h >>> 20) ^ (h >>> 12);
  return h ^ (h >>> 7) ^ (h >>> 4);
}

Set

Set 的实现类基于 Map 实现

  • HashSet 通过 HashMap 实现
  • TreeSet 通过 TreeMap 实现

HashSet

没有重复元素的集合,由 HashMap 实现,不保证顺序,允许使用 null。非同步。

public class HashSet<E>
    extends AbstractSet<E>
    implements Set<E>, Cloneable, java.io.Serializable

TreeSet

有序 Set 集合,基于 TreeMap 实现,非同步的

public class TreeSet<E> extends AbstractSet<E>
    implements NavigableSet<E>, Cloneable, java.io.Serializable {

Enumeration Vs Iterator

枚举类和迭代器,都能用来变量集合,他们都是接口

public interface Enumeration<E> {
    boolean hasMoreElements();
    E nextElement();
}

public interface Iterator<E> {
    boolean hasNext();
    E next();
    void remove();
}

Enumeration 只能够读取集合数据,不能修改;而 Iterator 能够删除

Iterator 支持 fail-fast 机制(多个线程对集合内容操作),而 Enumeration 不支持。

Comparable Vs Comparator

Comparable 是排序接口,一个类如果实现了 Comparable 接口,意味着该类支持排序。

public interface Comparable<T> {
    public int compareTo(T o);
}

通过 x.compareTo(y) 函数比较 x, y 大小,返回负数则 x < y, 返回 0 则 x=y,返回正数则 x>y

Comparator 是比较接口,如果要控制某个类的次序,而类本身不支持排序(没有实现 Comparable 接口)那么可以建立一个类比较器。

public interface Comparator<T> {
    int compare(T o1, T o2);
    boolean equals(Object obj);
}

Comparable 相当于“内部比较器”,而 Comparator 相当于“外部比较器”。如果你无法修改某个类来改变其实现,而又想要让他实现排序,那么只能够使用外部比较器了。

equals Vs ==

== 作用是判断两个对象地址是否相等,即判断两个对象是不是同一个对象。

equals 作用也是判断两个对象是否相等,但有两种情况:

  • 类没有覆盖 equals 方法,等价于 ==
  • 类覆盖了 equals 方法,若相同,则返回 true

reference


2015-09-20 java , jdk , design-pattern , collection

GitLab 学习笔记

Here is some config file paths and some commands I used to deal with GitLab. This is a learning note, not an instruction of installing GitLab on your server. For the detail of installation, please check the official site and playlist I create on Youtube.

gitlab icon

config

gitlab 主要配置目录 /etc/gitlab/gitlab.rb

command

  • gitlab-ctl reconfigure always run this command after modifying the config file /etc/gitlab/gitlab.rb. All the config files are generated by this command and located under opt/gitlab/embedded/service/gitlab-rails/config.

  • gitlab-ctl start|stop|restart start stop and restart gitlab service

  • gitlab-ctl status 输出类似下面的格式:

      run: logrotate: (pid 744) 197s; run: log: (pid 737) 197s
      run: nginx: (pid 743) 197s; run: log: (pid 731) 197s
      run: postgresql: (pid 748) 197s; run: log: (pid 738) 197s
      run: redis: (pid 746) 197s; run: log: (pid 734) 197s
      run: sidekiq: (pid 747) 197s; run: log: (pid 736) 197s
      run: unicorn: (pid 745) 197s; run: log: (pid 735) 197s
    
  • gitlab-ctl tail trace the log, and check error

  • gitlab-ctl tail postgresql 单独查看 postgresql 日志

file path

  • /opt/gitlab gitlab 和依赖应用的代码

  • /var/opt/gitlab/bin gitlab-ctl reconfigure 命令写入的地方,存放应用数据和配置文件 /etc/gitlab omnibus 版本 gitlab 的配置文件,平常只需要修改这个配置文件就够了

  • /var/opt/gitlab/git-data/repositories all the repo are stored here.

  • /var/log/gitlab 包含 omnibus 版本 gitlab 所有组件的日志数据

  • /var/opt/gitlab/nginx/conf/ nginx.conf and gitlab-http.conf

GitLab SMTP setting

official document is here

Following is my setting to use 163 NetEase’s SMTP service. But after I test for a while, most of GitLab emails were blocked by the service. So I change my setting to use mailgun.

# If your SMTP server does not like the default 'From: gitlab@localhost' you
# can change the 'From' with this setting.
# 网易服务器 smtp 机器要求身份验证帐号和发信帐号必须一致
# 如果用户在发送邮件时,身份验证帐号和发件人帐号是不同的,因此拒绝发送。
gitlab_rails['gitlab_email_from'] = 'username@163.com'
gitlab_rails['gitlab_email_reply_to'] = 'username@163.com'

#send gitlab notification via SMTP by 163.com
gitlab_rails['smtp_enable'] = true
gitlab_rails['smtp_address'] = "smtp.163.com"
gitlab_rails['smtp_port'] = 25
gitlab_rails['smtp_user_name'] = "username@163.com"
gitlab_rails['smtp_password'] = "smtp password"
gitlab_rails['smtp_domain'] = "163.com"
gitlab_rails['smtp_authentication'] = "login"
gitlab_rails['smtp_enable_starttls_auto'] = true

This is my setting for mailgun

# Sending email via SMTP using mailgun, following is the config
gitlab_rails['smtp_enable'] = true
gitlab_rails['smtp_address'] = "smtp.mailgun.org"
gitlab_rails['smtp_port'] = 587
gitlab_rails['smtp_user_name'] = "gitlab@domain.com created in the console of mailgun"
gitlab_rails['smtp_password'] = "password created in the console of mailgun"
gitlab_rails['smtp_domain'] = "your domian.com same as the @domain.com"
gitlab_rails['smtp_authentication'] = "login"
gitlab_rails['smtp_enable_starttls_auto'] = true

##Ref

http://doc.gitlab.com/omnibus/


2015-09-20 gitlab , git , notes

1980也不会存在的爱情

莫名奇妙的陪同学看了这场电影,看之前完全没有了解,只是听说这部电影是在他们那里拍摄的,其他的一无所知。而看之前也同样在豆瓣了解过,5.2的评分让我完全不抱希望,只是同学一再推荐就去了。

1980年代的爱情

只是一部文艺电影,坐在电影院里我一再告诫自己,于是电影就开始了。开场部分大段大段的自白,缓慢的镜头,那个叫做公母寨的地方确实很美,其实整个故事很简单,一个下乡的青年遇到了曾经的初恋,发生了一段美好的故事,虽然结局很悲惨,但过程很美好。这是一个很美好的青春故事,夹杂着那个时代,那个地点特有的符号,特有的宁静,特有的风景,原本应该是一个既能看风景又能看颜值的美好爱情片,却分分钟让我出戏,太过文艺的对白,让我觉得整个过程就像是两个人在背书,虽然作为一个90后并不知道80年代人们的对话,但是总觉得如电影中那样的对话是不大会出现的,你能随口一句话就能引发人生无限思考还能保证押韵?其二就是无法忍受的慢镜头,虽然爱情片总该有那两个镜头能够让人感受到浪漫,但,但对我来说更多的是无聊的等待,当然也有一些记忆深刻的镜头,就比如那个两人坐在竹桥上彻夜谈天,男主吹口琴的瞬间让人感觉到了些许浪漫。其他的镜头和叙述真的很让人出戏。

不过还有些需要被提起的,乡长和老田真是片中最喜欢的两个角色了,在这样的怀旧爱情片中能够出现这样的小插曲还是挺好,一个就是男主和乡长同上厕所,一个就是男主女友来找老田在楼下扫地说,饭菜能准备,床没法准备,再一个就是乡长拿错男主写的情书的时候。也就这样的时候让人会心的一笑。

如果按照观影风向标的打分标准来说,我可以给的分数分别是剧情5分,表演4分,可以给乡长和老田5分,而娱乐性是2分,有一个好的故事却没有一个会讲故事的好导演,哎。

当然此类电影的出现本来就是值得赞扬的,电影院长期被小时代,匆匆那年等等青春爱情片占领的时候出现这样一部稍微文艺一点的爱情片的时候,也不能苛求过多,只是这部电影能让我记住的也就只有那山间的风景了,远眺满山的茶树,中间些许采茶人,也有一条或隐或现的小道,主人公走在这条小路上去找女主的爸爸。

而对比我们的邻居韩国,他们一向以爱情片为人所知,但当然他们什么类型片都能产出了的,但他们拍摄爱情片总让人不能忘却,我的野蛮女友已经过了十多年,我依然会为男女主角的美好爱情所感动,我脑海中的橡皮擦,这只是一部偶然间看过的电影却让我无法忘怀,假如某一天我失忆了,我的另一半会有这样的坚持,陪我重走一遍曾经走过的地方吗?而假如爱有天意,讲过去的爱情故事,其实和这部1980有着相同的背景,却拍出来完全不一样的感觉,这些韩国电影却总有一两个镜头让人无法忘却,总有一两首让人记忆犹新,而回想这部片子,我真的已经想不到什么了,那两首出现过的歌,真是让看得我无比的尴尬,那真的是那个时代人唱的歌嘛?

而更加让我无法接受的便是片尾追加的几十年过后,一次同学聚会,一次滚床单,一次拒绝,而后又是几十年的离别,最后男主想要回到那个宁静的山村的时候,女主却得绝症去世了。世上有这样巧的事情,真巧想到她的时候,她就不再了?虽然知道电影是由小说改编,可是这样的离奇巧合让我无法接受更让我无法接受的是女主嫁人,而丈夫车祸去世了,女主还得了绝症,这是再拍韩剧么?如果导演或者小说作者想要在最后营造悲伤氛围的话,这并不是最佳的方法,我们的眼泪并不会这么留下来,而在此过程中我看到的是男主作为一个男人无法承担起的责任,虽然女主怕步她母亲的后尘怕连累男主,而选择留在山村,如果说女主留在山村最后的目的只是照顾年老的父亲的话,那么父亲去世之后,她便没有了继续留着的理由,她也有理由追寻自己的梦想,追寻自己的理想,甚至是追寻自己的情人,虽然片中并没有对女主有太多的感情描写,但我坚信女主并不是不喜欢男主,不然何必几年前给的笔记本还留着,几年前给的口琴还留着,当然这也可能只是故事太过悲剧,我并不想接受而已啦,我只是尽可能的讲了我的感受,我并没有看过小说或者了解过作者和导演本身。

而最后片中浅尝辄止的历史背景,大家都知道77年恢复高考,78年改革开放,而之前是整整十年的浩劫,乡政府的老田,我倒是很愿意听一听老人家的故事,女主的建筑师父亲,我也愿意听一听您的故事,那是真真的爱情,虽然片中老田也说过了,他说他并不记恨他的妻子,但是他们有感情,虽然那可能并不是我们通常说的爱,而桥梁建筑师的爱情则更加让人惋惜,老人会后悔一辈子吗?电影中也没有交代,只是给了一个老人看着墙上妻子的照片久久不能走动的背影。或许是因为审查的关系亦或许导演或者作者想要说明什么,这世上的爱情并不是什么天长地久,而是就是远隔天涯也能默默的祝福彼此。

http://movie.douban.com/review/7601848/


2015-09-17 影评 , 霍建起 , 野夫

电子书

最近文章

  • 专业医学信息网站整理 前两天鼻炎又犯了,去过很多次医院,也去过不同的医院,有说是慢性鼻炎,有说是过敏性鼻炎,这次检查说是鼻窦炎,总之就是鼻炎了。也尝试过各种药,各种滴鼻液,各种喷雾剂,各种洗鼻水,总是能缓解一段时间,然后到秋冬季节就又会差很多。也不知道是不是环境导致,毕竟大学毕业后还没有在不同城市生活过。所以上一次去了医院之后就在想,对于有些病,或者有些病理信息,是不是我可以在互联网上获得一些信息,然后自我调理,而这两天正好看到 Twitter 上有人提起,所以就整理一下。
  • 给博客添加 PWA 改造网站支持 Progressive Web Apps (PWA),改善移动端体验。
  • Linux 下找出重复文件 rdfind - find duplicate files in linux 安装使用:
  • 使用 timeshift 来备份和还原系统 Linux Mint 自带的备份和还原工具就是 timeshift, 今天看到有人贡献 timeshift 的命令行版本,突然意识到这个工具其实还有命令行版本。
  • 复式记账 很早就听闻了复式记账这个名词,一直在我的 TODO 上没来得及消化,记得当时主要是看了 wzyboy 和 byvoid 二位的文章,我相信我关注的不同的人选择同样的方式来做一件事情,肯定是有意义的。所以当时我就将复式计帐和 Beancount 放到了我的 Trello 待办事项里面,这几天终于有时间来了解一下了。