Nick Shek's Blog

學習Latex

近期對Latex相當有興趣, 之前曾經稍為在Wiki了解過Latex,覺得Symbol好像看起來好像好複雜,所以便提不起興趣學了。 直至近期發現好多整齊漂亮的pdf文件原來都是由Latex的編譯器建立,便開始想了解一下,當學習一個全新的markup language。 以下的範例會建立一個pdf文件,簡單地記綠「Today I Learned」,好像https://github.com/thoughtbot/tilhttps://github.com/jbranchaud/til,只是用Latex編寫而已,雖然這個情況或者用markdown會比較合適,但是用來練習Latex也不錯:

首先安裝 texlive:

sudo apt-get install texlive-full

Text Editor 我覺得用atom便好了無需再額多安裝 texmaker。反正本身電腦只使用了128G SSD, 沒有太多空間...

之後把以下原始碼儲存為main.tex,不妨花點時間了解一下latex語法,推薦不妨抽少少時間看看Latex in 157 minutes


\documentclass{article} \usepackage{hyperref} \RequirePackage{fontspec} \RequirePackage{xeCJK} \setCJKmainfont{Droid Sans Fallback} \XeTeXlinebreaklocale "zh" \XeTeXlinebreakskip = 0pt plus 1pt \title{Today I learned.今日我所學} \author{Nick Shek} \date{2017-02-07} \begin{document} \maketitle \clearpage \tableofcontents \clearpage \section{MySQL} \begin{itemize} \item Setting up MySQL replication without the downtime: \href{https://plusbryan.com/mysql-replication-without-downtime}{https://plusbryan.com/mysql-replication-without-downtime} \end{itemize} \section{Latex} \begin{itemize} \item Latex 中文化解決方案: \begin{itemize} \item \href{https://goo.gl/6ajvrM}{https://goo.gl/6ajvrM} \item \href{http://pangomi.blogspot.hk/2012/11/latex-in-ubuntu.html}{http://pangomi.blogspot.hk/2012/11/latex-in-ubuntu.html} \end{itemize} \item Create Table of contents in Latex \href{https://www.sharelatex.com/learn/Table\_of\_contents}{https://www.sharelatex.com/learn/Table\_of\_contents} \end{itemize} \end{document}

確保Droid Sans Fallback字型已經安裝後,執行

xelatex main.tex

如無意外,便能成功建立一個pdf,及中文字型能正確顯示。

參考了不同網站後,現在總算能輕鬆建立pdf,而pdf本身能顯示中文。 了解Latex基本Symbol後,其實建立一份Latex 沒有想像中那麼複雜。

如有興趣,也不妨看看: https://github.com/nickshek/latex-til

有時間的話會不定期更新

Source: http://milq.github.io/install-latex-ubuntu-debian/

用ansible去傳送電子郵件

Ansible在前幾年是一個非常熱門的開源項目,以我理解ansible其中一個功能是可用來部署應用程式,但是我個人覺得部署應用程式暫時有 capistrano或deployer-php也非常足夠,同時部署應用程式於多個伺服器也勝任有餘,總比手動部署來得有效率。

因此比起用Ansible來去試一試寫一個部署scripts,我想使用Ansible試一試一個簡單的例子去在各server 執行一些command (e.g df -h),再把結果以電子郵件傳送,這樣也可以感受一下Ansible的威力,雖然個人比起編寫yaml (yaml 內或text template 可以使用 jinja2 template language,一個類似Django template engine的template engine),個人更喜愛寫Ruby 或 PHP scripts 。

首先在/etc/ansible/ansible.cfg 設定 host_key_checking = False,這樣會令測試ansible時簡單一點,ansible.cfg 的範例如下所示:

[defaults]
host_key_checking = False
log_path=/path/to/log

之後建立一個ansible playbook e.g site.yml

- hosts: all:!local
  tasks:
  - name: ping all hosts
    ping:
    register: ping_result
    ignore_errors: yes

  - name: check disk space for all hosts
    command: df -h
    register: disk_result
    ignore_errors: yes

  - name: check high cpu usage process
    shell: ps -eo pcpu,user,args | sort -r -k1 | head -n5
    register: cpu_result
    ignore_errors: yes

  - name: run ifconfig
    shell: ifconfig
    register: ifconfig_result
    ignore_errors: yes

  - name: template email
    local_action: template src=./files/email_template.j2 dest='./tmp/{{ hostvars[inventory_hostname]["inventory_hostname"] }}.txt'

- hosts: local
  tasks:
  - name: create result email
    template: src=./files/email_summary_template.j2 dest=./tmp/email.txt
    delegate_to: localhost

  - name: send email result
    local_action: mail host='{{ email_host }}' port='{{ email_port }}' to='{{ email_to }}' username='{{ email_username }}' password='{{ email_password }}' subject='Report' body='{{ lookup("file", "./tmp/email.txt") }}' from='{{ email_from }}' charset='UTF-8' subtype='html'

以上的yaml script的流程好簡單,純粹用ping + shell module在不同的server 去執行不同的指令,之後用register 去把執行結果紀錄至指定的variable。因為萬一執行時出現錯誤,我們還是希望ansible playbook可繼續執行,因此設定ignore_errors = true即可。

下一步便是把各servers的執行結果變為一個template,因為這個執行結果在local machine的下一個tasks是需要的,所以使用了local_action

以下便用 email_template.j2 的原始碼:

{% if ping_result is defined %}
<h2>Ping Command Result</h2>
-----------------------------------<br/>
{{ ping_result | to_nice_yaml | replace("\n","<br/>") }}
<br/>
{% endif %}

{% if disk_result is defined %}
<h2>Disk Command Result</h2>
-----------------------------------<br/>
{{ disk_result | to_nice_yaml | replace("\n","<br/>") }}
<br/>
{% endif %}

{% if cpu_result is defined %}
<h2>Command result for ps -eo pcpu,user,args | sort -r -k1 | head -n5</h2>
-----------------------------------<br/>
{{ cpu_result | to_nice_yaml | replace("\n","<br/>") }}
{% endif %}
<br/>

執行結果是一個python 的 dict,為了確保所有的內容都被列印出來,純粹用to_nice_yaml 列印出來即可。 一下步便是把每一個inventory的執行結果整理至一個email template,然後寄出。email_summary_template.j2的內容如下所示:

{% for host in groups['all'] %}
{% if host != 'localhost' %}
<h1>Result for
{{ hostvars[host]['inventory_hostname'] }}
</h1>
<b>==================================================================</b><br/>
{{lookup("file", "./tmp/" + hostvars[host]["inventory_hostname"] + ".txt")}}
{% endif %}
{% endfor %}

請注意,send email result的這個tasks全部都使用了variable,避免直接寫死任何容易更改設定在 playboook內,這一個動作明顯不符合Ansible本身的哲學,variable可以放在group_vars/all :

---
email_host: <email_host>
email_port: <email_port>
email_to: <email_to>
email_username: <email_username>
email_password: <email_password>
email_from: <email_from>

ansible的建議資料夾結構請參考 http://docs.ansible.com/ansible/playbooks_best_practices.html#directory-layout

最後我們還是編寫hosts 檔案,以下是hosts的檔案範例,建議先設定ssh key來做認證,小心保管好private key + public key,避免把密碼寫在hosts file

[local]
localhost ansible_connection=local

[servers]
<example1.com> ansible_user=<example_user1> ansible_port=<example_port1> ansible_ssh_private_key_file=.ssh/id_rsa
<example1.com> ansible_user=<example_user2> ansible_port=<example_port2> ansible_ssh_private_key_file=.ssh/id_rsa

設定方法可參考 https://blog.longwin.com.tw/2005/12/ssh_keygen_no_passwd/

執行ansible playbook的方法相當簡單,如下所示:

ansible-playbook -i hosts site.yml

這樣我們便完成了一個好簡單的ansible playbook,這個playbook也有相當多的改進的地方,例如我們都把tasks 都放在site.yml,現在還好,沒有太多tasks。但沒有按roles去把不同的tasks放入去長遠都會有維護上的問題,site.yml愈簡單愈容易維護,另外一個可以改進的地方是lookup時的錯誤處理。

想知道這個project的檔案結構,可參考 https://github.com/nickshek/ansible_mail_example