Linux 交换分区

Linux 内核为了提高读写效率与速度,会将文件在内存中进行缓存,这部分内存就是 Cache Memory(缓存内存)。即使你的程序运行结束后,Cache Memory 也不会自动释放。这就会导致你在 Linux 系统中程序频繁读写文件后,你会发现可用物理内存变少。

Linux divides its physical RAM (random access memory) into chucks of memory called pages. Swapping is the process whereby a page of memory is copied to the preconfigured space on the hard disk, called swap space, to free up that page of memory. The combined sizes of the physical memory and the swap space is the amount of virtual memory available.

Swap space in Linux is used when the amount of physical memory (RAM) is full. If the system needs more memory resources and the RAM is full, inactive pages in memory are moved to the swap space. While swap space can help machines with a small amount of RAM, it should not be considered a replacement for more RAM. Swap space is located on hard drives, which have a slower access time than physical memory.Swap space can be a dedicated swap partition (recommended), a swap file, or a combination of swap partitions and swap files.

Linux 通过一个参数 swappiness 来控制 swap 分区使用情况,swappiness 是控制系统使用 swap 分区的频率阈值,当 swappiness = 100 时,系统会积极使用 swap 分区,而当 swappiness = 0 时,系统会最大限度的使用物理内存。

Swappiness is a property for the Linux kernel that changes the balance between swapping out runtime memory, as opposed to dropping pages from the system page cache. Swappiness can be set to values between 0 and 100 inclusive. A low value means the kernel will try to avoid swapping as much as possible where a higher value instead will make the kernel aggressively try to use swap space. The default value is 60, and for most desktop systems, setting it to 100 may affect the overall performance, whereas setting it lower (even 0) may improve interactivity (decreasing response latency.)[1]
In short:
vm.swappiness = 0 - it will swap only to avoid an out of memory condition
vm.swappiness = 60 - default value
vm.swappiness = 100 - it will swap aggressvely
To temporarily set the swappiness in Linux, as root you set the value to 100 with the following command: echo 100 > /proc/sys/vm/swappiness
Permanent changes are made in /etc/sysctl.conf via the following configuration line (inserted if not present previously): vm.swappiness = 100

临时修改 swappiness 值可以通过以下两种方式:

手动修改文件

vim /proc/sys/vm/swappiness
# or
echo 10 > /proc/sys/vm/swappiness

或者

sysctl vm.swappiness=10

永久修改 swappiness 参数的方法就是在配置文件 /etc/sysctl.conf 里面修改 vm.swappiness 的值,然后重启系统

echo 'vm.swappiness=10' >>/etc/sysctl.conf

swap 分区操作

查看 swap 分区大小及使用情况,使用 free 命令

free -h

也可以使用 swapon 查看 swap 分区信息

swapon -s                   # --summary 显示 swap 的使用情况
swapon --show               # 显示结果更好看

也可以直接查看文件

cat /proc/swaps             # 和 swapon -s 相同

关闭交换分区

swapoff /dev/mapper/VolGroup00-LogVol01

缩小 swap 分区

lvreduce -L 8G /dev/mapper/VolGroup00-LogVol01

格式化 swap 分区

mkswap /dev/mapper/VolGroup00-LogVol01

启动 swap 分区,并增加到 /etc/fstab 自动挂载

swapon /dev/mapper/VolGroup00-LogVol01

swap 分区建立

在装完 Linux 系统之后,建立 Swap 分区有两种方法:

  1. 新建磁盘分区作为 swap 分区
  2. 用文件作为 swap 分区

swap 分区大小设置

4G 以内的物理内存,SWAP 设置为内存的 2 倍。
4-8G 的物理内存,SWAP 等于内存大小。
8-64G 的物理内存,SWAP 设置为 8G。
64-256G 物理内存,SWAP 设置为 16G。

新建磁盘分区作为 swap 分区

以 root 身份登入控制台,输入

swapoff -a              #停止所有的 swap 分区

用 fdisk 命令对磁盘进行分区,添加 swap 分区,新建分区,在 fdisk 中用”t”命令将新添的分区 id 改为 82(Linux swap 类型),最后用 w 将操作实际写入硬盘

fdisk /dev/sdb

格式化 swap 分区,这里的 sdb2 要看您加完后 p 命令显示的实际分区设备名

mkswap /dev/sdb2

启动新的 swap 分区

swapon /dev/sdb2

为了让系统启动时能自动启用这个交换分区,可以编辑 /etc/fstab, 加入下面一行

/dev/sdb2 swap swap defaults 0 0

使用文件作为 swap 分区

创建要作为 swap 分区的文件:增加 1GB 大小的交换分区,则命令写法如下,其中的 count 等于想要的块的数量(bs*count= 文件大小)。

dd if=/dev/zero of=/root/swapfile bs=1M count=1024

格式化为交换分区文件:

mkswap /root/swapfile #建立 swap 的文件系统

启用交换分区文件:

swapon /root/swapfile #启用 swap 文件

使系统开机时自启用,在文件 /etc/fstab 中添加一行:

/root/swapfile swap swap defaults 0 0

2018-04-02 linux , swap , partition

使用 Phabricator 来review

Phabricator 是最早发源于 Facebook 的代码review工具, 后来创始人离开 Facebook 独立开发这款工具. Phabricator 和同类型的 Google 的 gerrit 有着相似的功能

  1. Phabricator 会将所有文件diff直接展开, 而Gerrit只有一个文件列表,需要点每一个文件看具体修改;
  2. admin的权限设置区别
  3. Phabricator 可以附加 unit test和以及格式检查和规范的工具(e.g. JSLint), 然后用户在上传diff的时候, Phabricator会自动用新版本代码去跑unit tests,以及运行JSLint, 然后在code review里面就可以看到unit tests有几个failure和error,以及JSLint的报警信息

Arcanist

Phabricator 提供了个命令行叫 arc (Arcanist),使用 arc 命令来连接开发者和 Phabricator 服务器。

安装 Arcanist

Mac OS

brew install node
npm install -g arcanist
arc help
arc upgrade

Ubuntu/Debian/Linux Mint

在 Linux 下使用

sudo apt update && sudo apt-get install php7.0-cli php7.0-curl php-pear

# 任意其它目录也可以
mkdir ~/phabricator
cd ~/phabricator
# 如果下载慢的话,可以先尝试设置一下proxy: export https_proxy="ip:3128"
git clone https://github.com/facebook/libphutil.git
git clone https://github.com/facebook/arcanist.git

# 编辑~/.bashrc,加入如下一行,之后source ~/.bashrc
export PATH="$PATH:$HOME/phabricator/arcanist/bin/"
# 如果没有项目配置,可以运行下面的命令设置全局的参数:
arc set-config default https://<phabricator server address>
arc install-certificate
# 按照屏幕提示,访问http://<phabricator server address>/conduit/token/ ,把token copy/paste下来
# 在~/.bashrc里添加下面两行
export EDITOR=vim
alias arc='LC_ALL=C arc'
# 并在命令行执行
source ~/.bashrc

Windows

自行处理: https://www.jianshu.com/p/a6ee738da1aa

配置

一般情况下在 HOME 目录下会产生一个 .arcrc 配置文件,格式类似下方:

{
  "config": {
    "default": "https://<phabricator server address>",
    "editor": "vim"
  },
  "hosts": {
    "https://<phabricator server>/api/": {
      "token": "cli-rdm2xxxxxxxxxxxx"
    }
  }
}

可以使用如下命令来更改该配置

arc set-config phabricator.uri "<phabricator server>"
arc set-config editor "vim"

本地开发流程

如下:

# 本地开发,新建feature
arc feature feature_1
# 或 git checkout -b feature_1
# 修改本地文件,然后提交
git add
git commit
 
# 提交code review
arc diff
# 通过--reviewers name参数可以指定reviewer
 
# 这里可以和一个Task(比如T123)关联起来,在Summary那个域里填上Ref T123,或者Fixes T123
# 两者的区别是Fixes在代码提交后会自动关闭Task,Ref不会
# 也可以提交code review之后,在浏览器里操作
 
# 本地修改后再次提交code review(这个revision是上次创建code review时的id,比如D1252)
arc diff --update 1252
# --update 1252 也可以不加,默认会合到上一个review中
 
# reviewer已经Accept之后,提交代码(不要用git push!):
arc land feature_1
# 如果报错找不到对应的revision,带上revision号(比如1252)运行:
arc land --revision 1252
# land之后,feature branch会被自动删除
# land 使用后会将当前分支 merge 或者squash merge 到master分支,提供详细的提交信息,推送到master并且删除本地分支

QA

问题: No changes found. (Did you specify the wrong commit range?)

答: Arcanist(arc) 是一个 pre-commit 或者说 pre-push 代码审查工具,一旦本地分支被push到origin,这就打破了 Arcanist 工具的意义,但是可以用以下方法来补救:

  • 删除当前分支的远端分支 git push origin --delete branch_name
  • 在使用 arc diff 时告诉分支需要和哪一个分支对比 arc diff origin/master
  • 或者显示指定 land 的目的地 arc land --onto master

2018-03-29 code review , git , version control , php , mysql , gerrit

使用 click 构造漂亮的Python命令行程序

Click 是 Python 下一款命令行库,可以用来快速轻松实现Python命令行程序。之前也介绍过一个 argparse ,但是要比 click 复杂很多,至少从代码上看。但是 click 其实也说了1 argparse 在标准库中,click 是依赖于 optparse 的,至于不基于 argparse 是因为 argparse 不支持嵌套,并且在 POSIX 兼容上有问题。

Click 被设计用来快速构建命令行程序,因此缺乏一些扩展性,比如他不允许高度定制help介绍。Click 是用来支持 Flask 开发框架的。

官网地址: http://click.pocoo.org

基本使用

# hello.py
import click
@click.command()
@click.option('--count', default=1, help='Number of greetings.')
@click.option('--name', prompt='Your name',
              help='The person to greet.')
def hello(count, name):
    """Simple program that greets NAME for a total of COUNT times."""
    for x in range(count):
        click.echo('Hello %s!' % name)

if __name__ == '__main__':
    hello()

然后可以这样运行该脚本 python hello.py --count=3,并且 Click 还会自动生成 help 信息。

Option 参数

Click 使用基本可以归纳为

  • 使用 @click.command() 装饰一个函数,使之成为命令行接口;
  • 使用 @click.option() 等装饰函数,为其添加命令行选项等。

最基础的用法, option 接受一个变量

@click.command()
@click.option('--n', default=1)
def hello(n):
    click.echo('hello' * n)

使用 --n=2 输出两遍

接受多个变量,需要使用 nargs 指定数量

@click.command()
@click.option('--pos', nargs=2, type=float)
def cal(pos):
    click.echo('%s / %s' % pos)

使用 --pos 5.0 4.0

如果参数是固定的几个值,可以使用可选项

@click.command()
@click.option('--hash-type', type=click.Choice(['md5', 'sha1']))
def digest(hash_type):
    click.echo(hash_type)

使用 --hash-type=md5 参数只能为 md5 或者 sha1,否则报错。

option 还有其他一些参数,比如 prompt 当用户忘记该参数时,将错误报出来,hide_input 可以隐藏输入,常用于密码输入,confirmation_prompt 验证输入等等。

Click 封装了

@click.password_option()
@click.confirmation_option(prompt='Are you sure you want to drop the db?')

argument 参数

和 Option 一样,Argument 最基础的应用就是传递一个简单变量值

@click.command()
@click.argument('input', type=click.File('rb'))
@click.argument('output', type=click.File('wb'))
def inout(input, output):
    while True:
        chunk = input.read(1024)
        if not chunk:
            break
        output.write(chunk)

reference

  1. http://click.pocoo.org/6/why/ 


2018-03-27 python , flask , click , command

每天学习一个命令:vnstat 统计服务器网卡流量

vnStat 是一款开源的网络流量统计工具,可以方便的查看当天,当月流量统计。官网地址:

https://humdi.net/vnstat/

安装

在 Debian/Ubuntu 下非常简单

sudo apt install vnstat vnstati

假设网卡名为 eth0,该配置在 /etc/vnstat.conf 中,安装结束后初始化数据库

sudo vnstat -u -i eth0

添加为开机启动

sudo update-rc.d vnstat enable

使用

直接输入 vnstat

vnstat -l  # 或者 `--live` 实时流量
vnstat -h  # 显示小时流量
vnstat -d  # 显示日流量信息
vnstat -w  # 显示周流量信息
vnstat -m  # 显示月流量信息
vnstat -t  # 显示流量最高top10天

图形化输出可以使用 vnstati ,将月流量统计图输出到图片

vnstati -i eth0 - -months - -output /dir/month.png

2018-03-26 linux , vnstat , network

Jigsaw Outline 部署和使用

官方主页: https://getoutline.org/en/home 项目地址: https://github.com/Jigsaw-Code

Outline 细分有三部分,分别是 Outline Manager, Outline Server 和 Outline Client。

  • Outline Manager:方便用户管理所有的 Outline Server,可以使用图形化界面快捷部署 Outline Server ,然后为每一位用户生成连接秘钥,使得用户可以安全连接 Outline Server 。
  • Outline Server:用来提供安全代理的服务,响应、验证 Outline Client 的所有请求,仅此而已。
  • Outline Client:用来向 Outline Server 发起请求,或接受其返回的数据,仅此而已。

部署服务端

在安装 Docker 之后安装

wget -qO- https://raw.githubusercontent.com/Jigsaw-Code/outline-server/master/src/server_manager/install_scripts/install_server.sh | bash

在脚本安装结束后会生成一段配置,复制并保存该配置,在客户端配置中需要使用。

客户端使用

先下载 Outline Manager,地址

https://github.com/Jigsaw-Code/outline-releases

下载其中的 Outline-Manager.AppImage ,这是 Linux 下的客户端,不同系统中下载不同客户端。然后在 Manager 中粘贴上面服务端配置,完成 Manager 配置。然后在 Manager 中点击 ADD KEY 生成可用的 KEY。点击分享将生成一个托管在 Amazon S3 上的静态网页,其中有 Shadowsocks 客户端的配置,将该字符串发送给客户端即可。

然后再下载 client 客户端,目前暂时 Jigsaw 还没提供 iOS 和 Mac 版本,但是 Windows 和 Android 客户端可以在 GitHub 和 Play Store 链接 找到。

在手机上输入上面 Manager 生成的 SS 配置即可连接。安装配置过程将 Shadowsocks 的部署配置流程完全简化了。期待Google Jigsaw 能够将这个项目继续维护下去吧。


2018-03-26 linux , docker , socks , google , vpn

使用 Python 下载抖音无水印视频

抖音 APP 中保存到本地就是无水印版本的,所以头条的服务器肯定是保存有无水印版本的抖音视频的,所以只要找到接口地址就可以搞定。先在网上搜罗了一圈,确实有人已经做了解析,还提供了收费解析服务

搜索之后发现又发现了同类型的其他

  • http://douyin.iiilab.com/
  • http://www.dyapp.cc/
  • https://app886.cn/douyin_video

分析接口

分析这几个页面就会发现他们通过分享的链接就能够拿到视频的直接链接肯定是通过接口获取的,所以通过 Android 抓包能找到类似下面的接口

https://aweme.snssdk.com/aweme/v1/play/?
video_id=v0200fd80000bejku38697aj8tin1brg
&line=0
&ratio=720p
&watermark=1
&media_type=4
&vr_type=0
&test_cdn=None
&improve_bitrate=0
&version_code=270

这个请求返回状态码是 302,返回的 response header 中 Location 标示了该视频的真实地址。

后来分析抖音的 Feed 流设计,又发现了另外一个接口

https://api.amemv.com/aweme/v1/play/?video_id=v0200fd80000bejhsoir863vmi5add60&line=0&ratio=720p&media_type=4&vr_type=0&test_cdn=None&improve_bitrate=0

也类似于上面的接口不过域名不同,参数也类似。

入手

入手的几个页面,分享页

https://www.iesdouyin.com/share/video/6604280853952466190/?region=CN&mid=6601014204340275975&u_code=df31b2ff&titleType=title
http://v.douyin.com/dqv3dv/

第二条是短链接,展开就是上面的长链接了。

在分享页面获取视频的 id,然后使用上面的链接获取视频的播放地址。

大致的思路如下

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import os
import re
from urllib.request import urlopen

import requests
from tqdm import tqdm


class DouyinVideoInfo:
    def __init__(self, vid, title='', nickname=''):
        self.video_id = vid
        self.title = title
        self.nickname = nickname


def download(url, filename, name):
    """
    :param url: 视频直接链接
    :param filename: 保存文件名
    :param name: 进度条内容
    :return:
    """
    file_size = int(urlopen(url).info().get('Content-Length', -1))

    if os.path.exists(filename):
        first_byte = os.path.getsize(filename)
    else:
        first_byte = 0
    if first_byte >= file_size:
        return file_size
    header = {"Range": "bytes=%s-%s" % (first_byte, file_size),
              'User-Agent': 'okhttp/3.10.0.1'}
    pbar = tqdm(total=file_size, initial=first_byte,
                unit='B', unit_scale=True,
                desc=name)
    req = requests.get(url, headers=header, stream=True)
    with(open(filename, 'wb')) as f:
        for chunk in req.iter_content(chunk_size=1024):
            if chunk:
                f.write(chunk)
                pbar.update(1024)
    pbar.close()
    return file_size


def down_by_vid(info: DouyinVideoInfo):
    r = requests.get('https://api.amemv.com/aweme/v1/play/', params={
        'video_id': info.video_id,
        'line': 0,
        'ratio': '720p',
        'watermark': 0,
        'media_type': 4,
        'vr_type': 0,
        'test_cdn': 'None',
        'improve_bitrate': 0,
        'logo_name': 'aweme'
    }, headers={
        'Host': 'api.amemv.com',
        'sdk-version': '1',
        'X-SS-TC': '0'
    }, allow_redirects=False)
    print(r.headers['Location'])
    download(r.headers['Location'], '{}.mp4'.format(info.video_id), info.title)


def get_video_info(long_url) -> DouyinVideoInfo:
    Headers = {
        'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8',
        'accept-encoding': 'gzip, deflate, br',
        'accept-language': 'zh-CN,zh;q=0.9',
        'cache-control': 'max-age=0',
        'upgrade-insecure-requests': '1',
        'user-agent': 'Mozilla/5.0 (Linux; U; Android 5.1.1; zh-cn; MI 4S Build/LMY47V) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/53.0.2785.146 Mobile Safari/537.36 XiaoMi/MiuiBrowser/9.1.3',
    }
    r = requests.get(long_url, headers=Headers)
    video_id = re.findall("(?<=video_id=).+?(?=&amp)", r.text)[0]
    title_name = re.findall("(?<=desc\">).+?(?=</p>)", r.text)[0]
    nick_name = re.findall("(?<=bottom-user\">).+?(?=</p>)", r.text)[0]
    info = DouyinVideoInfo(video_id, title_name, nick_name)
    return info


if __name__ == '__main__':
    d1 = 'https://www.iesdouyin.com/share/video/6604280853952466190/?region=CN&mid=6601014204340275975&u_code=df31b2ff&titleType=title'
    d2 = 'https://www.douyin.com/share/video/6536906252729978119/?region=CN&mid=6441083920867035918&titleType=title&timestamp=1522052360&utm_campaign=client_share&app=aweme&utm_medium=ios&iid=27151889375&utm_source=copy'
    info = get_video_info(d2)
    down_by_vid(info)

2018-03-25 douyin , 抖音 , python

使用 netlify 托管静态网站

netlify 是一个提供静态网站托管的服务,提供CI服务,能够将托管 GitHub,GitLab 等网站上的 Jekyll,Hexo,Hugo 等静态网站。

Netlify is a unified platform that automates your code to create high-performant, easily maintainable sites and web apps.

Netlify 有如下的功能:

  • 能够托管服务,免费 CDN
  • 能够绑定自定义域名,支持SSL证书
  • 支持自动构建
  • 提供 Webhooks 和 API

使用

Netlify 的使用非常直观和简单,和网站的自我介绍和定位一样简答,使用 GitHub 登录,然后获取公开项目的授权,让其获取源码,然后指定编译命令,比如我的网站使用 Jekyll,那么编译命令就是

jekyll build

将生成的静态网站放到

_site

这个目录下,接下来的事情就是等着 Netlify 自动编译部署,默认情况下 Netlify 会分配一个随机的子域名 https://<随机字符>.netlify.com 这样的地址,可以在设置中设置为自己想要的域名,或者在设置中绑定自己的域名。

那接下来就是 Netlify 会在每一次提交commit时自动编译部署静态网站。最后来访问下 https://blog.einverne.info

联想

同类型的静态网站托管服务, GitHub Page 原生支持,绝大部分常用的功能 GitHub Page 也都支持,不过是 GitHub 在国内的访问一般。另外 Pancake.io 可以将 Dropbox 中的静态内容映射成网站也同样支持绑定域名,Postach.io 能够将 Evernote 作为blog发布的源。

其他一些同类型的服务,now 同样能够托管静态网站,不过也支持托管 Node.js。Firebase Hosting随同 Firebase 一同提供,更加推荐作为产品介绍静态页面来托管,不要将其作为博客内容托管。Surge 静态网站托管,支持命令行上传代码。


2018-03-24 github , git , ci , website

Linux 下使用命令获取硬盘信息

本文主要是一些和硬盘相关的命令,包括如何查看硬盘的型号,容量,还有硬盘上的分区情况,来详细了解本机硬盘的状态。

hdparm

如果想要在 Linux 下查看硬盘信息,可以使用命令 hdparm 。这个命令可以用来查看硬盘制造商,序列号等等有用信息。man hdparm 中告诉我, hdparm 命令是用来查看或者设置 SATA/IDE 设备参数的。

查看设备信息

假设本地有设备 /dev/sda 那么可以使用

hdparm -I /dev/sda

来查看该设备的信息

/dev/sda:

ATA device, with non-removable media
        Model Number:       Netac SSD  240G
        Serial Number:      5002B725438XXXX
        Firmware Revision:  O1217A
        Transport:          Serial, ATA8-AST, SATA 1.0a, SATA II Extensions, SATA Rev 2.5, SATA Rev 2.6, SATA Rev 3.0
Standards:
        Supported: 9 8 7 6 5
        Likely used: 9
Configuration:
        Logical         max     current
        cylinders       16383   16383
        heads           16      16
        sectors/track   63      63
        --
        CHS current addressable sectors:   16514064
        LBA    user addressable sectors:  268435455
        LBA48  user addressable sectors:  468862128
        Logical  Sector size:                   512 bytes
        Physical Sector size:                   512 bytes
        Logical Sector-0 offset:                  0 bytes
        device size with M = 1024*1024:      228936 MBytes
        device size with M = 1000*1000:      240057 MBytes (240 GB)
        cache/buffer size  = unknown
        Nominal Media Rotation Rate: Solid State Device
Capabilities:
        LBA, IORDY(can be disabled)
        Queue depth: 32
        Standby timer values: spec'd by Standard, no device specific minimum
        R/W multiple sector transfer: Max = 2   Current = 2
        DMA: mdma0 mdma1 mdma2 udma0 udma1 udma2 udma3 udma4 udma5 *udma6
             Cycle time: min=120ns recommended=120ns
        PIO: pio0 pio1 pio2 pio3 pio4
             Cycle time: no flow control=120ns  IORDY flow control=120ns
Commands/features:
        Enabled Supported:
           *    SMART feature set
                Security Mode feature set
           *    Power Management feature set
           *    Write cache
           *    Look-ahead
           *    Host Protected Area feature set
           *    WRITE_BUFFER command
           *    READ_BUFFER command
           *    NOP cmd
           *    DOWNLOAD_MICROCODE
                SET_MAX security extension
           *    48-bit Address feature set
           *    Device Configuration Overlay feature set
           *    Mandatory FLUSH_CACHE
           *    FLUSH_CACHE_EXT
           *    SMART error logging
           *    SMART self-test
           *    General Purpose Logging feature set
           *    WRITE_{DMA|MULTIPLE}_FUA_EXT
           *    {READ,WRITE}_DMA_EXT_GPL commands
           *    Segmented DOWNLOAD_MICROCODE
           *    Gen1 signaling speed (1.5Gb/s)
           *    Gen2 signaling speed (3.0Gb/s)
           *    Gen3 signaling speed (6.0Gb/s)
           *    Native Command Queueing (NCQ)
           *    Host-initiated interface power management
           *    Phy event counters
           *    READ_LOG_DMA_EXT equivalent to READ_LOG_EXT
           *    DMA Setup Auto-Activate optimization
                Device-initiated interface power management
           *    Software settings preservation
                Device Sleep (DEVSLP)
           *    SMART Command Transport (SCT) feature set
           *    SCT Write Same (AC2)
           *    SCT Features Control (AC4)
           *    SCT Data Tables (AC5)
           *    DOWNLOAD MICROCODE DMA command
           *    WRITE BUFFER DMA command
           *    READ BUFFER DMA command
           *    Data Set Management TRIM supported (limit 8 blocks)
           *    Deterministic read ZEROs after TRIM
Security:
        Master password revision code = 65534
                supported
        not     enabled
        not     locked
                frozen
        not     expired: security count
                supported: enhanced erase
        2min for SECURITY ERASE UNIT. 2min for ENHANCED SECURITY ERASE UNIT.
Device Sleep:
        DEVSLP Exit Timeout (DETO): 40 ms (drive)
        Minimum DEVSLP Assertion Time (MDAT): 31 ms (drive)
Checksum: correct

测试读取速度

hdparm 提供了一个简单的读速度测试参数

hdparm -Tt /dev/sda

结果

/dev/sda:
 Timing cached reads:   25572 MB in  2.00 seconds = 12798.56 MB/sec
 Timing buffered disk reads: 800 MB in  3.01 seconds = 266.08 MB/sec

能够看到 2 秒内读取了 25572M 缓存,而在 3 秒内从磁盘上物理读 800M 数据。

fdisk

fdisk 主要用来查看和修改硬盘分区表,它能够识别 GPT,MBR,BSD 等等分区表。设备可以被划分为一个或者若干逻辑磁盘,这些逻辑磁盘叫做分区。这些分区信息被包含在分区表 (partition table) 中,通常在硬盘的 sector 0 中保存。

设备名通常叫做 /dev/sda/dev/sdb 等等,设备的名字通常指整块硬盘,分区名字通常是设备名后面加上分区的序号,比如 /dev/sda1 表示的是第一块硬盘上的一个分区。详细的信息可以在 Linux kernel 文档 Documentation/devices.txt 文件中找到。

GPT

GPT 的全称是 GUID Partition Table,全局唯一标识分区表,指的是一个实体硬盘的分区表结构布局标准。1 GPT 使用 64 bit 逻辑块地址。

MBR

MBR 全称为 Master Boot Record,主引导扇区, DOS type。Sector 0 是被 4 个主分区 primary partition 描述占用的,逻辑分区 (Logical partition) 从序号 5 开始。

如果要查看硬盘的分区情况,可以使用 fdisk

fdisk -l

结果

Disk /dev/loop0: 81.7 MiB, 85692416 bytes, 167368 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes


Disk /dev/loop1: 81.7 MiB, 85639168 bytes, 167264 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes


Disk /dev/loop2: 81.6 MiB, 85549056 bytes, 167088 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes


Disk /dev/sda: 223.6 GiB, 240057409536 bytes, 468862128 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x5ad18deb

Device     Boot Start       End   Sectors   Size Id Type
/dev/sda1          63 468862127 468862065 223.6G 83 Linux


Disk /dev/sdb: 931.5 GiB, 1000204886016 bytes, 1953525168 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 4096 bytes
I/O size (minimum/optimal): 4096 bytes / 4096 bytes
Disklabel type: dos
Disk identifier: 0x29049925

Device     Boot      Start        End    Sectors   Size Id Type
/dev/sdb1  *            63  629153594  629153532   300G  7 HPFS/NTFS/exFAT
/dev/sdb2        629153656 1953523711 1324370056 631.5G  f W95 Ext'd (LBA)
/dev/sdb5        629153658 1153466999  524313342   250G  7 HPFS/NTFS/exFAT
/dev/sdb6       1153467063 1782588464  629121402   300G  7 HPFS/NTFS/exFAT
/dev/sdb7       1782589440 1798213631   15624192   7.5G 82 Linux swap / Solaris
/dev/sdb8       1798215680 1953523711  155308032  74.1G 83 Linux

Partition 1 does not start on physical sector boundary.
Partition 5 does not start on physical sector boundary.
Partition 6 does not start on physical sector boundary.


Disk /dev/sdc: 119.2 GiB, 128035676160 bytes, 250069680 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x326f11b9

Device     Boot     Start       End   Sectors   Size Id Type
/dev/sdc1  *           63 248346992 248346930 118.4G  7 HPFS/NTFS/exFAT
/dev/sdc2       248348672 250066943   1718272   839M 27 Hidden NTFS WinRE

dd

dd 工具是一个专业的测试工具,对测试结果不苛求可以用来做 IO 读写的简单评估。首先要了解两个特殊设备:

/dev/null 伪设备,回收站.写该文件不会产生IO
/dev/zero 伪设备,会产生空字符流,对它不会产生IO

dd 命令使用:

dd if=/dev/zero of=/tmp/test bs=1G count=1 oflag=dsync
  • if 用来设置dd命令读取的输入文件名
  • of dd 输出文件名
  • bs 设置dd命令读取的块大小
  • count dd 命令读取的块个数
  • oflag=dsync 使用同步I/O 去除 caching 影响

综上

测试硬盘写速度

sync; dd if=/dev/zero of=tempfile bs=1M count=1024; sync

测试磁盘读速度

dd if=tempfile of=/dev/null bs=1M count=1024

GUI

同样在 Linux 下也可以使用 GUI 图形化的工具来查看,搜索菜单 Disks,然后就能查看当前电脑安装的硬盘了。

  1. https://en.wikipedia.org/wiki/GUID_Partition_Table 


2018-03-24 linux , hard-drive , ssd

每天学习一个命令:ncdu 磁盘分析工具

最近想把机械硬盘换成 SSD,然后使用 du -h 查看了一下本地硬盘使用,发现用了180多G,想要清理一下废弃的大文件,然后就发现了这个非常好用的磁盘管理工具 ncdu。 Ubuntu 源下有这个软件,可以直接使用命令安装:

sudo apt install ncdu

使用

终端下直接使用 ncdu ,然后工具就会直接扫描当前目录,并且按照文件及文件夹占用大小,从大到小排列,例如:

   22.2 GiB [#####     ] /Documents
   16.2 GiB [###       ] /.local
.  13.7 GiB [###       ] /.cache
   10.9 GiB [##        ] /.m2
   10.8 GiB [##        ] /Dropbox
    9.8 GiB [##        ] /Git
    3.2 GiB [          ] /.IntelliJIdea2016.3
    2.2 GiB [          ] /.pyenv
    1.4 GiB [          ] /.IdeaIC2016.3
    1.3 GiB [          ] /.wiznote

在界面中按下 ? 就会发现很多快捷键

┌───ncdu help─────────────────1:Keys───2:Format───3:About──┐
│                                                          │
│       up, k  Move cursor up                              │
│     down, j  Move cursor down                            │
│ right/enter  Open selected directory                     │
│  left, <, h  Open parent directory                       │
│           n  Sort by name (ascending/descending)         │
│           s  Sort by size (ascending/descending)         │
│           C  Sort by items (ascending/descending)        │
│           d  Delete selected file or directory           │
│           t  Toggle dirs before files when sorting       │
│           g  Show percentage and/or graph                │
│                        -- more --                        │
│                                         Press q to close │
└──────────────────────────────────────────────────────────┘

看到这个快捷键,就可以疯狂的使用d 来删除不再使用的大文件了。

最后开心的按下 q 退出。


2018-03-23 linux , ubuntu , ncdu , disk

使用 clonezilla 备份和恢复

Clonezilla 是一个分区和硬盘镜像和克隆的工具。Clonezilla 能够实现硬盘到硬盘,分区到分区的快速拷贝,在备份文件,克隆系统的应用中有着非常高的性能。使用起来也非常的方便,因此平时都保留着一个 8G U 盘制作的 Clonezilla 可以启动 U 盘。

Clonezilla is a partition and disk imaging/cloning program

下载地址: http://clonezilla.org/downloads.php

制作 U 盘启动

制作一个 bootable Clonezilla 非常简单,在官网现在 iso 镜像之后,使用镜像写入工具就可以制作可以启动的 Clonezilla。在 Windows 下可以使用 Universal usb installer,或者 unetbootin,Linux 下使用 etcher。几乎都是加载 iso,选择写入设备,写入的过程比较简单,就不展开具体教程了。

备份流程

使用制作好的 U 盘启动,需要调整 PC 启动顺序,然后进入 clonezilla 系统,在 Clonezilla 中可以选择硬盘到硬盘复制,分区到分区复制,还有网络的备份,SSH 的备份,这些不怎么常用就暂时省略,主要使用硬盘到硬盘的备份和分区到分区的备份。

在具体的使用过程中遇到了一系列的问题,比如 Clonezilla 中无法找到新加的磁盘,比如如何将大容量的分区拷贝到小容量的分区中。不过这些问题都一一得到了解决。下面就讲下这些问题的解决方案。

Clonezilla 无法找到新加的磁盘

在电脑上直接插上新的 SSD,有可能默认情况下新的 SSD 没有分区,磁盘上也没有新建的分区表。这个时候 Clonezilla 就无法在分区到分区的拷贝中找到新的磁盘的分区。因此需要使用 Live boot 的 Linux mint U 盘启动,在 U 盘启动的 Linux 中使用 GParted 来针对新的磁盘进行分区。一般情况下直接划分一个系统分区就足够了。

划分分区的时候可能会遇到 MBR(Master Boot Record) 和 GPT(GUID Partition Table) 这样两个分区表的名词,这两个都是硬盘分区表的格式,不过一老一新。

MBR 主引导记录,是传统的分区机制,MBR 支持 32 位或者 64 位系统,但是支持的分区数量有限,并且不支持超过 2T 的硬盘。

GPT 是全局唯一标识分区表,是一个新的分区机制,解决了 MBR 很多缺点。支持大于 2T 的磁盘,fdisk 命令最大只能建立 2T 分区,需要使用 parted 命令来创建大于 2T 的分区。GPT 向后兼容 MBR,必须在支持 UEFI 的硬件上才能使用。

可以使用

sudo parted /dev/sdb print

来查看 sdb 这块硬盘上的分区表。关于 parted 命令更多的介绍,可以参考这篇文章

如果使用 GUI,那么在 U 盘启动的 Linux 中使用 GParted 可以直接对硬盘进行分区,然后应用即可,当新硬盘有分区时,Clonezilla 就能够找到分区并将原先的分区克隆到新的分区中了。

将大容量 HDD 拷贝到小容量的 SSD

Clonezilla 只能够将小的分区复制到大的分区中,因此会面临一个大问题。比如有一块 1T 的机械硬盘,需要将其中的一个 500g 的分区克隆到 250G 的 SSD 中,那么就需要先将 500G 的分区缩小到 250G 以下。查看当前 500G 系统分区实际文件占用大小,实际使用量一定要小于 250G,删除无用文件将实际占用文件缩小到 250G 以下之后,可能需要一个可以启动的 Linux live CD,一般情况下我也会制作一个 Linux Mint 的可启动 U 盘,然后启动该 U 盘,在 Linux Mint 中,使用 GParted 调整需要克隆的分区大小,将分区调整到 250G 以下。搜索关键词 shrink partition。缩小分区操作可能因不同硬盘和文件占用而不同耗时,一般情况下也需要非常长时间的操作。

在缩小分区之后,就可以启动 Clonezilla 然后使用分区到分区的操作,将原先 HDD 上的系统分区拷贝到 SSD 的分区中。拷贝也是一个非常耗时的操作,等待拷贝完成,这样系统就在原来分区和 SSD 上各有一份拷贝了。

由于 Clonezilla 在拷贝时是原样复制,因此可能导致 Linux 分区的 UUID 也一模一样,因此需要根据这篇文章 来修改 Linux 分区的 UUID。

接下来的事情就是修改引导,让电脑启动到 SSD 中的系统。

这里就要推荐一个软件 boot-repair

sudo add-apt-repository ppa:yannubuntu/boot-repair
sudo apt-get update
sudo apt-get install -y boot-repair && boot-repair

需要在 Live boot 的 Linux mint 中启动 boot-repair 来修复确实的引导。然后开机启动新硬盘上的系统就 OK 了。

reference


2018-03-23 clonezilla , tutorial , backup , restore , system , ssd , linux

电子书

最近文章

  • 使用 Huginn 搭建自己的 IFTTT IFTTT, Zapier
  • notion 使用记录 很早就有人推荐 Notion,但是注册了用了一下,本以为就是一个在线的 Google Docs,可昨天在豆瓣看到一篇文章介绍比 Trello 更加智能的代替品,然后一看就是 Notion,于是就再来研究下 Notion。然后发现原来 Notion 可以是 Google Calendar, 可以是 Trello,可以是 Google Docs,可以是 todo list,可以是 Google Excel。甚至可以导入 word,markdown,html,csv。
  • Google Cloud Platform 使用向导 Google Cloud 提供 300 刀的初始优惠,而最近我的 Linode 节点越来越不稳定,时常撞墙,所以不得不再别人强烈推荐下注册了一下 GCP。这里就记录一下遇到的问题,其他具体的细节网上已经够多,就不再赘述。
  • html 转 pdf 命令行工具 wkhtmltopdf 最近因为用 HTML 写了一个文档,当想要输出时保存为 PDF,而 Chrome 自带的打印功能,本来就能够快速的保存为 PDF,但是却保留不了页面中的链接,所以找到了这个 wkhtmltopdf.
  • freemarker Java 模板引擎 FreeMarker is a free Java-based template engine, originally focusing on dynamic web page generation with MVC software architecture. However, it is a general purpose template engine, with no dependency on servlets or HTTP or HTML, and is thus often used for generating source code, configuration files or e-mails. by wikiPedia