kodi 盒子上的媒体中心?

经常听说 Kodi,却一直没有时间了解一下,最近整理盒子 应用,突然间想起了这个被很多人称为的神器。

什么是 Kodi

Kodi 是一个强大媒体播放软件,支持 Macos, Windows, Linux, iOs 以及 Android 等众多平台,能在各种手机、电脑、平板以及机顶盒中运行。并且因为 Kodi 强大的媒体播放能力,被很多人成为家庭影院必不可少的应用。Kodi 拥有上千种插件,大大扩展了它的功能,丰富的 Kodi 插件为 Kodi 提供了无数的可能。Kodi 的插件种类很多,有音视频源插件,有字幕插件,有影视内容索引插件,有链接搜索助手插件等等。

下载并安装 Kodi

从官网上下载 kodi 写下文章时最新的版本为 17.6,选安卓 64 位

Kodi:https://kodi.tv/

备份地址:

  • http://mirrors.kodi.tv/releases/android/arm64-v8a/kodi-17.6-Krypton-arm64-v8a.apk
  • https://mirror.de.leaseweb.net/xbmc/releases/android/arm64-v8a/kodi-17.6-Krypton-arm64-v8a.apk

比如要在斐讯盒子 T1 中安装 Kodi,首先去盒子的设置 - 高级 - 远程调试打开,如果可能就把盒子的 IP 设置为固定 IP,这个 IP 下面命令中需要使用到。

通过 adb 安装过程如下:

adb connect <ip>
adb shell
adb install /path/to/kodi.apk

设置 Kodi

中文设置

  1. 初次进入 Kodi,选择左侧最上方三个按钮中的第二个图标“system”
  2. 选择“Interface settings”,点击左侧最下方的“Basic”菜单,点 3 次切换到“Expert”模式
  3. 选择“Skin”,更改“Fonts” 为 “Arial based”
  4. 点击左侧 “Regional” 菜单
  5. 更改“Character set” 为 “Chinese Simplified(GBK)”,更改“Language”为“Chinese Simple”
  6. 上述步骤严格按照顺序操作

添加文件安装源

  1. 点击“系统”-“系统设置”,点击左侧最下方的“基础”菜单,点 3 次切换到“专家”模式
  2. 点左侧的“插件”菜单,把“未知来源”项打开
  3. 返回到系统菜单,进入“文件管理”(file manager)
  4. 点击“添加源”,比如输入路径:http://srp.nu, 为源取个名字,更多的源地址,可以看下文
  5. 回 KODI 主页,点击“插件”,点左侧最上方第一个图标“插件浏览器”
  6. 选“从 zip 文件安装”,选择之前设定的名字,安装 zip 文件
  7. 安装完成后,返回上一级,选“从库安装”
  8. 选中需要安装的插件,安装

kodi repo 源

如何安装源这里有两篇详细的图文教程可以参考:

  • https://www.vpnranks.com/kodi-repositories/
  • https://www.vpnranks.com/superrepo-kodi-repository/
  • https://github.com/taxigps/xbmc-addons-chinese/
  • http://archive.org/download/repository.xvbmc
  • https://kodiapps.com/builds-chart
  • https://fusion.tvaddons.co/
  • http://lvtvv.com/repo/
  • http://kodi.emby.media

在安装插件源的时候可能会遇到这几个名词

  • 14.x Helix
  • 15.x Isengard
  • 16.x Jarvis
  • 17.x Krypton

其实这是 Kodi 的版本代号。

总结

其实看到这里就能看到 Kodi 其实绝大部分的功能都是可代替的,流媒体播放固然强大,但是我更喜欢将资源通过 samba 共享出来,在盒子上使用小白播放器,或者在手机上使用 ES Explorer 访问;Kodi 中的直播流功能强烈的依赖于整理好的直播流,而盒子上的超级直播,HDP 直播等等 应用都能很好的代替直播流;再其次 Kodi 带的 DLNA,AirPlay 投屏功能,其实装一个乐播投屏就能完美解决,更不用说我之前的两台海美迪自身就携带 DLNA,局域网投屏本身问题也不大;最后再是 Kodi 的强大的插件库,虽然强大,却无奈经年无人维护,虽然有无数的插件可以使用,却只有寥寥几个可用。所以最后其实 Kodi 也不是居家必备的良药,对于折腾我始终抱有这样的态度,用起来比怎么用要重要的很多,真正用起来才是一个软件应该提供的,我在盒子上话费时间最多的其实就是播放本地局域网共享的视频,其实本身这个功能并不需要那么强大的 Kodi,当然 Kodi 也可以,至于强大的媒体库,对于我这样看完就删,真的只有经典的才保存的玩家来说,太奢侈。


2018-03-03 android , tv , kodi , media

使用Python控制Headless Chrome

首先要解释一下 Headless Chrome,通俗的讲就是运行一个没有GUI的Chrome,在 Headless Chrome 出现以前有 PhantomJS ,但是自从 Headless Chrome 出现之后 PhantomJS 活跃度下降,所以维护者就宣布 了停止继续开发。那么 Headless Chrome 能够什么呢?自动化测试,网页截图,网络调试,爬虫等等任务。Google 说在可预见的未来会一直维护

关于 Headless Chrome 官方有两篇教程

在 Headless Chrome 之前使用 Python 可以结合Chrome推出的 chromedriver 来操作 PhantomJS,那么现在有了Chrome的Headless模式怎么来控制Chrome就是这篇文章要讲的内容。

Chrome DevTools Protocol

在此之前几个重要的网址:

Google官方维护了一份协议叫做 Chrome DevTools Protocol,只要是实现了这一份协议就能够编程来控制Chrome,Chrome 自带的开发者工具其实也是这一份协议的实现

再看几个 Chrome Devtools Protocol 中的概念:

  • Browser 实例可以拥有多个 Page
  • Page 拥有至少一个 frame: main frame, 其他的 frame 可能被网页标记 iframe 和 frame 创建
  • Frame 拥有一个可执行的上下文,在该上下文中 JavaScript 可以被执行,Frame 中也可能有浏览器扩展 extensions 产生的内容被执行

可以用这张 来显示其结构。

常用API

  • Browser 浏览器版本,关闭,命令行等等管理操作
  • Page 该域包含和页面相关接口,页面加载,资源内容,截图,打印等
  • Network 网络请求,Cookie,缓存,证书等内容
  • DOM 文档DOM的获取,修改,删除等
  • Runtime 该域下暴露 JavaScript 相关运行时接口,可以用来执行代码

本地启动 Headless Chrome

本地启动 Headless Chrome 可以参考这篇文章

如果需要使用 Docker 来启动Headless Chrome 也可以使用

docker run -it --rm --name alpine-chrome -p 9222:9222 einverne/alpine-chrome

更加具体的使用介绍可以查看 GitHub

启动之后可以访问: http://localhost:9222/json 来查看是否启动成功。

pychrome

pychrome 是 Chrome Devtools Protocol 的 Python 实现,其他语言的实现,可以查看这个项目。Chrome官方推荐js/nodejs的实现 chrome-remote-interface 还有 node.js 实现的更高层级的 Puppeteer

这里主要摘录几个常用的操作

截图

使用 Page.captureScreenshot

def screenshot(browser, url, filename='image.png'):
    tab = browser.new_tab()
    tab.start()
    tab.call_method('Page.navigate', url=url, _timeout=5)
    tab.wait(10)
    # 截取当前Tab屏幕,结果为图片内容Base64
    screen_base64 = tab.call_method("Page.captureScreenshot")
    image_data = screen_base64.get('data', '')
    with open(filename, 'wb') as f:
        f.write(image_data.decode('base64'))
    tab.stop()
    browser.close_tab(tab) 

打印PDF

同样使用 Page 下方法

def print_to_pdf(browser, url, filename='file.pdf'):
    tab = browser.new_tab()
    tab.start()
    tab.call_method('Page.navigate', url=url, _timeout=5)
    tab.wait(10)
    pdf_data = tab.call_method('Page.printToPDF', landscape=False).get('data')
    with open(filename, 'wb') as f:
        f.write(pdf_data.decode('base64'))
    tab.stop()
    browser.close_tab(tab)

向下翻页

def perform_input(browser):
    """向下浏览页面"""
    tab = browser.new_tab()
    tab.start()
    tab.Page.enable()
    tab.Page.navigate(url='https://www.douban.com/', _timeout=5)
    tab.wait(5)
    # 更多 keycode 可以参考 https://msdn.microsoft.com/en-us/library/dd375731(VS.85).aspx
    keycode = int(0x22)
    tab.Input.dispatchKeyEvent(type='keyDown', windowsVirtualKeyCode=keycode, nativeVirtualKeyCode=keycode)
    tab.wait(3)
    screen_base64 = tab.call_method("Page.captureScreenshot")
    image_data = screen_base64.get('data', '')
    with open("keyDown.png", 'wb') as f:
        f.write(image_data.decode('base64'))
    tab.stop()
    browser.close_tab(tab)

获取网页HTML

获取动态网页的网页内容,等待JS执行完成后获取HTML

def get_html(browser, url):
    tab = browser.new_tab()
    tab.start()
    tab.call_method('Page.navigate', url=url, _timeout=5)
    tab.wait(10)
    html = tab.Runtime.evaluate(expression="document.documentElement.outerHTML")
    tab.stop()
    browser.close_tab(tab)
    return html['result']['value']

操纵网页元素注入JS

下面这段代码是访问 baidu,输入关键字,并点击搜索按钮,解析搜索结果并打印

def perform_click(browser):
    tab = browser.new_tab()

    # def loading_finished(**kwargs):
    #     print "[loading finished]"
    #
    # # when HTTP request has finished loading
    # tab.set_listener("Network.loadingFinished", loading_finished)

    tab.start()

    # call method
    # tab.Network.enable()
    tab.Network.enable()
    tab.Page.enable()
    tab.Runtime.enable()

    def dom_content_event_fired(**kwargs):
        print "[content] dom content event fired"
        tab.DOM.enable()
        root = tab.DOM.getDocument()
        root_node_id = root.get('root', {}).get('nodeId', '')
        # 找到输入框
        input_box = tab.DOM.querySelector(nodeId=root_node_id, selector='#kw')
        # tab.DOM.setNodeValue(nodeId=input_box, value='hello')
        tab.Runtime.evaluate(expression='document.getElementById("kw").value="Chrome"', )
        # 找到搜索按钮
        search_btn = tab.DOM.querySelector(nodeId=root_node_id, selector='#su')
        remote_node = tab.DOM.resolveNode(nodeId=search_btn.get('nodeId', ''))
        # 执行点击
        tab.Runtime.callFunctionOn(functionDeclaration='(function() { this.click(); })',
                                   objectId=remote_node.get('object', {}).get('objectId', {}))
        tab.wait(3)
        # 输出结果
        html = tab.Runtime.evaluate(expression="document.documentElement.outerHTML")
        html_value = html.get('result', {}).get('value', '').encode('utf-8')
        soup = BeautifulSoup(html_value, 'html.parser')
        l = soup.select('h3 > a')
        for result in l:
            print result.text
            print result['href']

        screen_base64 = tab.call_method("Page.captureScreenshot")
        image_data = screen_base64.get('data', '')
        with open("test.png", 'wb') as f:
            f.write(image_data.decode('base64'))

        # tab.DOM.performSearch(query='xpath', includeUserAgentShadowDOM=True)
        # stop the tab (stop handle events and stop recv message from chrome)
        tab.stop()

        # close tab
        browser.close_tab(tab)

    tab.set_listener("Page.domContentEventFired", dom_content_event_fired)

    # tab.call_method("Page.reload", ignoreCache=False)
    tab.call_method("Page.navigate", url='https://www.baidu.com', _timeout=5)
    tab.wait(20)

完整的代码可以参考 GitHub

其他可学习的网站

这篇文章讲述了使用 nodejs 的库 NickJS来爬取网站的要点。

这篇使用 nodejs 的chrome-remote-interface,来抓取网页。

其他

  • https://stackoverflow.com/questions/28430479/using-google-chrome-remote-debugging-protocol
  • https://blog.phantombuster.com/web-scraping-in-2017-headless-chrome-tips-tricks-4d6521d695e8
  • https://stackoverflow.com/questions/7848878/how-to-use-google-chrome-remote-debugging-protocol-in-http
  • https://github.com/auchenberg/devtools-remote
  • https://github.com/auchenberg/chrome-devtools-app
  • https://intoli.com/blog/running-selenium-with-headless-chrome
  • https://duo.com/blog/driving-headless-chrome-with-python

2018-03-01 chrome , headless-chrome , linux , python

Linux 下的 Android emulators

待办事项中一直有一个 Genymotion 模拟器的处理,挂在待办已经好几个月了,终于有时间来找一找 Linux 的安卓模拟器了, Genymotion 曾经很好用,可惜的是如今似乎已经收费。

Official

当然第一想到的就是 Android 开发者官网上提供的官方模拟器,虽然早先被诟病不少,但是似乎更新迭代很快速,现在几乎没有什么特别大的问题。

Anbox

这是我 Google 出来的第二个结果,他官网的标语就是可以再 GNU/Linux 系统上运行任何 Android 应用程序。根据官网的介绍, Anbox 和 Genymotion 的虚拟化不一样, Genymotion 是在操作系统上完整的虚拟化整个系统,而 Anbox 直接使用宿主机的硬件和内核来运行 Android 程序。目前 Anbox 没有可视化界面可以安装 Apk,可以使用命令 adb install path/to/app.apk 来安装。

Anbox 这个项目还是属于起步阶段,但是体验还是非常不错的,如果遇到安装之后无法打开,或者无法安装 Failure [INSTALL_FAILED_NO_MATCHING_ABIS: Failed to extract native libraries, res=-113] 这种错误时,也不沮丧。

如果要在 Anbox 中安装 arm 和 Google Play 可以参考这个项目

官网地址:https://anbox.io/

Genymotion

很可惜的是他已经不再提供免费的开发者 License。

官网:https://www.genymotion.com/

reference


2018-02-28 android , linux , emulator

Grafana 基本使用

Grafana 是一个开源的时序性统计和监控平台,或许用这么简单的一句话无法表现 Grafana 的强大。下面是官方列出的 6 大功能,但其实细分起来 Grafana 要强大更多。

  • 可视化
  • 报警
  • 支持很多数据源,InfluxDB,Elasticsearch,MySQL 等等
  • 全平台支持
  • 无数的 dashboardsplugins
  • 支持用户系统和协作

更多 Feature 见 官网

安装

非常简单,官网就很详细

默认的账户密码都是 admin

基本概念

Data Source

数据源:正式的支持以下数据源 Graphite, InfluxDB, OpenTSDB, Prometheus, Elasticsearch, CloudWatch。从 4.3 版本开始支持 MySQL。

每个数据源都有一个独立的查询编辑器,用来动态从数据源获取数据,并展示到 Panel 上。

Organization

组织:支持多组织,以支持各种部署模式,包括使用单个 Grafana 实例为多个组织提供服务。

用户、数据源和仪表板都隶属于组织。

用户隶属于某个组织后。就拥有该组织下的所有数据源和仪表板。

User

用户: Grafana 的帐户。用户可以属于一个或多个组织,并可以通过角色分配不同级别的权限。

Role

在给每个新用户分配组织时,可以指定其角色。角色有:Admin、Editor 、Read Only Editor、Viewer。默认为 Viewer。

Dashboard

仪表板:由一行或多行的面板组成。仪表板可以看做为一个展示单元(栏目),该单元由一行或多行组件构成,每行又可以由一个面板或多个面板组成。

仪表板的时间段可以由仪表板右上方的仪表板时间选择器控制。

Row

行: 仪表板内的逻辑分隔符,用于将面板组合在一起。一行里可以有一列或多列面板。

Panel

面板:Grafana 的可视化构建块,所有的数据展示都是在面板上实现的。

每个面板都有各种各样的造型和格式化选项,让你创建完美的图片。

目前有四种面板类型:Graph,Singlestat,Dashlist,Table 和 Text。

  • Graph 面板允许你根据需要绘制出许多指标和系列。
  • Singlestat 面板需要将单个查询减少到单个数字。
  • Dashlist 和 Text 是不连接到任何数据源的特殊面板。

可以通过插件安装的方式来扩展面板类型。例如:Pie Chart、Worldmap Panel。

面板上的时间范围通常是仪表板时间选择器中设置的时间范围,但可以通过使用面板特定时间覆盖来覆盖。

Query Editor

查询编辑器:用来显示数据源,并根据数据源查询其包含的指标。

将鼠标放在面板的 Panel Title 位置,然后单击,就会显示出查询编辑,点击 Edit,就显示出查询编辑器了。

Grafana 允许您在查询编辑器中按照它们所在的行来引用查询。如果您向图形添加第二个查询,则可以通过键入#A 来引用第一个查询。这提供了一种简单而方便的方法来构建复合查询。

Templating

模板允许更多的交互式和动态的仪表板。可以让你轻松的批量生成同一类型的查询,而不用一个个添加这些 Panel。

可以根据需要自定义变量参数作为查询查询条件,这些变量参数可以是固定的,也可以是通过应用服务提供的数据,还可以是数据源动态查询的数据。

配置

如果是使用的 deb 安装,配置文件路径

/etc/grafana/grafana.ini

[database]

此处的数据源与前面提到的数据源不同,此处的数据源用来存储 Grafana 的用户、仪表板等 Grafnan 自身的信息。

默认用 sqlite3 数据源,一般也不用修改,也可以修改为 MySQL。

[security]

默认的 Grafana 管理员用户名为 admin,密码为 admin,可以进行修改,管理员密码也可以在页面中修改。

admin_user = admin
admin_password = admin

[users]

用户设置

# 是否允许新用户注册,默认为 true,如果不想让人随意注册,可以关闭
allow_sign_up = false

# 是否允许用户自己创建组织,默认为 true,为了便于管理,组织统一由管理员创建,不允许普通用户创建
allow_org_create = false

# 是否将新用户自动归属到主要的组织上(组织 id=1)。当设置为 false 时,将自动为该新用户创建一个新的组织。
auto_assign_org = true

# 新用户默认的角色
auto_assign_org_role = Viewer

其他更多见 官网

Dashboard 及语句

在 Grafana 中使用 SQL 语句,这部分待补充

Plugins

Grafana 支持非常多的插件,可以扩展数据源,或者扩展显示,或者用来增强一些功能。


2018-02-27 grafana , go

搭建自己的文件共享服务 linx server

之前用过 https://sm.ms 这个非常好用的图片共享站,界面非常简洁,延迟也低,就想着是不是自己也能够搭建一套这样的服务私用,然而 sm.ms 并没有开源,连其 Android/iOS 客户端也并没有开源,所以只能在网上寻觅代替品,幸而遇到了 linx server

同样是一个文件分享的站点,通过 Docker 搭建一套服务非常简单,他也能够支持使用 API 上传,界面也同样非常简洁。具体的使用可以参考 Docker 页面

docker pull einverne/linx-server
docker run -p 8080:8080 -d -v /media/meta:/data/meta -v /media/files:/data/files einverne/linx-server

2018-02-26 linux , server , file , media , sharing , photo , linx-server

Workflow for iOS 使用指南

Workflow 是 iOS 上一款可以实现自动化过程的应用,在 iOS 的框架内是先自定义的流程,比如发送最后拍摄的一张照片到 Instagram 这样的操作。他被 Apple 买下之后就免费开放给所有人使用了。有效的使用 Workflow 能够简化在手机上重复的操作。

Workflow 的功能应该由使用者决定,而不是开发者,所以 Workflow 和编程语言一样,需要学习。

Workflow

下面先介绍一些 Workflow 能够做到的事情,然后从中去学习 Workflow 制作的过程,从而能够自己完成自动化流程。

图片九宫格

将方形图片切割为 9 格图片,Workflow 地址

Google 粘贴板

用 Google 搜索当前粘贴板中的文字或者图片,Workflow

隐身相机

在不启动相机界面的同时拍照,并保存到相册, Workflow 地址 这一个 Workflow 只有一个选项选择前置还是后置摄像头,如果你想要更加复杂的 Workflow 允许你选择连拍数量的可以使用这个

下载到小米路由器

在手机上复制下载链接运行该 Workflow 即可,地址

切分全景图

将横向的全景图切分为多个图片方便分享到 Instagram,地址

每天领取支付宝红包

支付宝去年推出的分享领红包活动,虽然一开始诚意满满,不过后来就只能每天领 1 毛了,不过 1 毛也是肉嘛,反正 Workflow 点一下够省事,地址

网易云音乐听歌识曲

一键打开网易云音乐听歌识曲,地址

网购历史价格查询

下载文件

下载文件到本地或者 Dropbox

下载 Instagram 图片和视频

下载 YouTube 视频

网购历史价格查询

获取 bilibili 视频封面

还有更多好用的可以从下面的网站上获取,我平时常用的

  • App Store 换区
  • Instagram 下载
  • Google 以图搜图

更多的 Workflow 可以从下面网址获取

还有一个实用技巧就是实用 Google 的 site 搜索语法,比如想要搜索 Instagram 相关的 Workflow,则可以在 Google 中输入 Instagram site:https://workflow.is/workflows/

如果你常用 RSS,那么可以在 InoReader 中订阅该组合包:http://www.inoreader.com/bundle/0014cd63bb38

自定义

通过上面的一些例子应该可以看到一些端倪,其实 Workflow 就是把一些常用的操作给编程化,比如最简单的支付宝领取红包,其实就是使用 Safari 打开一个链接。如果再复杂一些比如切割图片,涉及到一些宽高计算,可能还有些 IF 的判断。如果再复杂一些比如 Instagram 图片下载,涉及到了下载网页内容用正则去匹配关心的内容,在比如 Google 以图搜图,涉及到了 Post 请求,然后拼凑网页链接再打开。

最最重要的一点就是网络服务提供足够的 API 能够让 Workflow 能够轻易的调用,如果有翻译服务提供了公开可调用的 API,我们就可以在 Workflow 中,获取粘贴板内容,将内容发送给翻译服务请求结果,并且将结果以通知或者其他形式告诉给用户,这样一个翻译的 Workflow 就实现了。

reference


2018-02-25 workflow , ifttt , automatic , ios

Squid http 代理

Squid 是一个Web代理软件,可以轻松的实现 HTTP,HTTPS,FTP 代理,通过缓存常用请求,Squid 能够减少带宽使用,提高响应速度。

sudo apt-get update
sudo apt-get install squid

Squid 的默认配置文件存放在 /etc/squid/squid.conf

sudo vim /etc/squid/squid.conf

Squid 的默认端口是 3128,配置文件中可以 http_port 3128 来设置

Squid 默认是不允许任何客户端连接的,通过修改配置允许所有客户端连接

http_access allow all

修改完成后重启代理服务

sudo service squid restart

reference


2018-02-24 linux , ubuntu , squid , proxy , webproxy , http , https

dockerfile 指令

通常情况下,我们并不使用 docker commit 方法来构建镜像,而是使用 Dockerfile 的定义文件和 docker build 命令来构建镜像。更多 Docker 入门 的内容可以参考之前的文章。

每条指令都会创建一个新的镜像层并对镜像进行提交,Docker 大致上按照下面的流程执行 Dockerfile 中的指令:

  • Docker 从基础镜像运行一个容器
  • 执行指令,对镜像做出修改
  • 执行类似 docker commit 的操作,提交一个新的镜像层
  • Docker 再基于刚刚提交的镜像运行一个新容器
  • 执行 Dockerfile 中下一个指令,直到所有指令执行完毕

常见的命令 RUNEXPOSE 之外,Dockerfile 还支持其他很多指令。

CMD

CMD 指令用于指定容器启动时要运行的命令,类似 RUN,但是 RUN 指令是指镜像被构建时要运行的命令,而 CMD 是指定容器被启动时要运行的命令。运行的命令放在一个数组结构中

docker run 命令可以覆盖 CMD 指令

如果 Dockerfile 有多个 CMD 指令,只有最后一个会生效。

CMD 指令有很多种格式,最常见,也是官方推荐的格式是:

CMD ["executable", "param1", "param2", ...]

ENTRYPOINT

ENTRYPOINT 指令和 CMD 指令非常类似,之前说过 CMD 指令会被 docker run 命令覆盖,而 ENTRYPOINT 指令提供的命令不容易在启动容器时被覆盖。实际上, docker run 命令行中的指定的任何参数都会被当做参数再次传递给 ENTRYPOINT 指令中指定的命令。

ENTRYPOINT 可以让容器以应用程序或者服务的形式运行。

ENTRYPOINT 也有很多使用方式,比较推荐的是:

ENTRYPOINT ["executable", "param1", "param2" ]

WORKDIR

WORKDIR 指令用来在从镜像创建一个新的容器时,在容器内部设置一个工作目录,ENTRYPOINT 或 CMD 指定的程序会在该目录下执行。

可以通过 -w 参数在运行时覆盖工作目录

sudo docker run -it -w /var/log ubuntu pwd

ENV

ENV 指令用来在镜像构建过程中设置环境变量,新的环境变量能在后续任何 RUN 指令中使用。

同样也可以使用 -e 参数赖在运行时添加环境变量。

USER

USER 指令用来指定镜像会以什么用户去运行

USER nginx

镜像会以 nginx 用户去运行,同样也可以使用 -u 选项来覆盖该指令

VOLUME

VOLUME 指令用来像基于镜像创建的容器添加卷,一个卷可以存在一个或者多个容器内的特定目录,这个目录可以绕过联合文件系统,提供共享数据或者对数据持久化功能。

  • 卷可以再容器间共享和重用
  • 对卷的修改是立即生效的
  • 对卷的修改不会对更新镜像产生影响
  • 卷会一直存在直到没有任何容器使用

卷功能让我们可以将数据,比如源代码,数据库等其他持久化内容添加到镜像中,而不是预先将这些内容提交到镜像内部,卷允许我们在多个容器间共享内容,可以利用此功能测试容器和内部应用代码,管理日志,处理内部数据库等等。

VOLUME ["/opt/project"]

该指令会基于此镜像创建的任何容器创建一个名为 /opt/project 的挂载点

ADD

ADD 指令用来将构建环境下的文件和目录复制到镜像中。

ADD 指令通过目的地址参数末尾的字符来判断文件源是目录还是文件,如果目标地址以 / 结尾,那么 Docker 就认为源地址指向的是一个目录,如果目的地址不是 / 结尾,那么源地址就是文件。

COPY

COPY 指令和 ADD 很类似,根本不同是 COPY 只关心在构建上下文中复制本地文件,而不会去做文件提取和解压的工作。

如果目的位置不存在, Docker 会自动创建所需要的目录结构

ONBUILD

ONBUILD 指令能为镜像添加触发器,当一个镜像被用作其他镜像的基础镜像时,该镜像中的触发器会被执行。触发器会在构建过程中插入新指令,我们认为这些指令是紧跟 FROM 之后执行的。触发器可以是任何构建指令。

reference

  • 《第一本 Docker 书》

2018-02-23 linux , docker , docker-image

Docker中运行 MySQL

mysql 是 Docker 和 MySQL 官方提供的一个镜像。

启动服务器实例

拉取镜像

docker pull mysql

启动镜像

docker run --name first-mysql -e MYSQL_ROOT_PASSWORD=password -d mysql:5.7

这样就创建了一个名为 first-mysql 的 mysql 5.7 实例。

Shell 中访问容器日志查看

docker exec -it first-mysql bash

日志

docker logs first-mysql

环境变量

当启动 mysql 容器时,可以传入环境变量来改变容器的配置:

  • MYSQL_ROOT_PASSWORD:必须。用于设置MySQLroot用户的密码
  • MYSQL_DATABASE:可选。用于指定镜像启动容器时要创建的数据库。如果提供了用户/密码,则会将该用户做为此数据库的超级用户。
  • MYSQL_USERMYSQL_PASSWORD:可选。用于创建一个新用户并设置密码。
  • MYSQL_ALLOW_EMPTY_PASSWORD:可选。设置为yes时,则可以使用空密码登录
  • MYSQL_RANDOM_ROOT_PASSWORD:可选。设置为yes时会为root用户设置一个随机密码(使用pwgen),所生成的随机密码会被输出到stdout
  • MYSQL_ONETIME_PASSWORD:可选。为root用户指定一个一次性密码,该密码会在用户首次登录时强制修改

数据存储

mysql 镜像创建容器时,数据库存储会以下面两种方式存储:

  • 数据卷容器:使用Docker默认的数据管理方式来管理数据库的数据存储,在这种方式下,数据库文件会被写入数据库的内部。这种方式对于用户非常简单,缺点是很在宿主机上找到所存储的数据。
  • 外部数据卷:在宿主机创建一个数据目录,再将数据目录挂载到容器内部。这种方式可以很方便的在宿主机上找到并进行数据管理,但需要确保数据目录的存在。

使用外部数据卷时,假设宿主机有 /my/data/ 目录,可以使用 -v 选项来讲宿主机挂载到容器:

docker run --name mysql -v /my/data/:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=password -d mysql:5.7

数据备份

docker exec first-mysql sh -c 'exec mysqldump --all-databases -uroot -p"$MYSQL_ROOT_PASSWORD"' > /some/path/on/your/host/all-databases.sql

在其他容器中连接mysql

官方的镜像中导出的是默认 3306 端口,其他容器可以使用 --link 参数来连接mysql容器

docker run --name other-app --link first-mysql:mysql -d other-application-use-mysql

2018-02-18 mysql , database , linux , docker

netdata 又一款 Linux 监控程序

任何服务器监控是一项很重要的事情,以前一直使用 nodequery ,虽然设置方便简洁,但是数据不够详细也是他很大问题,所以经过一番寻找又发现了这个 netdata。下面是 netdata 一系列的特性

  • 安装方便,几乎是一键
  • 实时信息显示,监控内容详细
  • 发送告警,可以向很多第三方平台发送报警通知,包括 telegram, email, slack channel 等等
  • 无磁盘 IO 操作
  • 不需要 root 权限
  • 可视化界面漂亮

官方提供了一些列的 demo : https://my-netdata.io/

一键安装

按照下面的教程安装:

https://github.com/firehol/netdata/wiki/Installation

现在官方也提供了 Docker 的方式安装,更加方便。

配置 Nginx

upstream backend {
	server 127.0.0.1:19999;
	keepalive 64;
}

server {
	listen 80;
	listen [::]:80;

	index index.html index.htm index.nginx-debian.html;

	server_name status.einverne.info;

	auth_basic "Protected";
	auth_basic_user_file passwords;

	location / {
		proxy_set_header X-Forwarded-Host $host;
		proxy_set_header X-Forwarded-Server $host;
		proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
		proxy_pass http://backend;
		proxy_http_version 1.1;
		proxy_pass_request_headers on;
		proxy_set_header Connection "keep-alive";
		proxy_store off;
	}
}

主要配置如上,可以加上一个密码保护,具体 Nginx 的配置 可以参考链接。

htpasswd -c -d /etc/nginx/passwords yourusername

这行命令中的 passwords 就是之前 Nginx 配置中的 auth_basic_user_file 后的参数,通过该选项设置用户名密码。

卸载删除

netdata 是不提供卸载脚本的,如果要在系统中删除,可以使用如下

killall netdata
apt-get remove zlib1g-dev gcc make git autoconf autogen automake pkg-config
rm -Rf /usr/sbin/netdata
rm -Rf /etc/netdata
rm -Rf /usr/share/netdata
rm -Rf /usr/libexec/netdata
rm -Rf /var/cache/netdata
rm -Rf /var/log/netdata
rm -Rf /opt/netdata
userdel netdata

2018-02-16 linux , vps , monitor

电子书

最近文章

  • 使用 assh 来管理 SSH config 前两天一直在思考如何管理我的 SSH config 配置,最后的解决办法就是通过 git 版本管理起来。但这两天由冒出一个新的问题,那就是经常在国内直连 aws 或者 oracle 的机器时 ssh 连不上,但是通过国内的 VPS 中转就非常快,那这就意味着,我每一次连接国外的机器时必须先登录腾讯云的机器,然后在从腾讯云的机器上连过去,有些麻烦,但那天在 Twitter 上看到有人分享了一个 SSH 管理的命令行工具 assh,大致的看了一下使用简介,通过配置就可以完美的解决这个问题。
  • 备份和恢复从 Chrome Webstore 中下架的 Google Chrome Extension 这两天重装系统同步 Chrome 的数据才发现,我一直使用的 Dream Afar New Tab 这个我用了很久的扩展从 Chrome Webstore 消失了,不清楚是 Google 主动下架,还是作者很久没有更新被 Webstore 下了还是为什么。但这个扩展经过了很多的 Chrome 版本依然运行良好至今为止都能每天给我提供世界不同地方的美景。
  • Docker 网络与容器互联 简单整理一下 Docker 中 network 子命令,以及 docker 中相关 network 方面的内容。
  • MacBook Pro 初始设置记录 这里就简单的记录一下我从 Linux Mint 迁移到 MacOS 根据我的个人需求来初始化新的 MacBook Pro 的一些设置,和一些基本的感想。下面的内容会按照我自身的需求出发,我会列举我想要的功能然后在此基础上我需要借助哪些工具来实现。在切换到 MacBook Pro 之前,我使用了大约 6 年多的 Linux Mint,我已经有一套我自己的 Workflow,在切换到 Mac OS 之前我就在想哪一些的事情我是必须有 Mac 的软硬件才能做到,并且很提高某一方面的效率的,我列了一些
  • 多设备间同步 ssh 配置及密钥 ssh 客户端会在用户目录 ~/.ssh/ 目录下存放配置信息 (~/.ssh/config) 和公钥和私钥,如果有多个设备不同设备间的同步和管理就会成为一个比较头疼的问题。我在 Reddit 上抛出这个问题 后,我本来想的是通过 git 版本控制来进行管理,但有人说因为公钥和私钥都是二进制的文件,其实没有必要使用 git,任何一个同步工具就能够解决。