2015年11月2日 星期一

[Linux] 透過 yum 安裝 Nginx 官方版 @ CentOS 6.6、nginx-1.8.0

最近在整理 yum server 才驚覺 nginx 沒有在 CentOS package 裡頭,同理 tmux 也是 Orz

$ vim /etc/yum.repos.d/nginx.repo
name=nginx repo
baseurl=http://nginx.org/packages/centos/6/$basearch/
gpgcheck=0
enabled=1

$ yum update
$ yum search nginx
Loaded plugins: security
============================================================= N/S Matched: nginx =============================================================
nginx-debug.x86_64 : debug version of nginx
nginx-debuginfo.x86_64 : Debug information for package nginx
nginx-nr-agent.noarch : New Relic agent for NGINX and NGINX Plus
nginx.x86_64 : High performance web server

$ yum install nginx
$ yum info nginx
Installed Packages
Name        : nginx
Arch        : x86_64
Version     : 1.8.0
Release     : 1.el6.ngx
Size        : 872 k
Repo        : installed
From repo   : nginx
Summary     : High performance web server
URL         : http://nginx.org/
License     : 2-clause BSD-like license
Description : nginx [engine x] is an HTTP and reverse proxy server, as well as
            : a mail proxy server.


對照 nginx.org 官方版本公告,其中 nginx-1.8.0 是 2015/04/21 釋放出的穩定版。

2015年10月30日 星期五

[Linux] Python Fabric - 在 SSH 架構上,進行服務部署 @ Ubuntu 14.04

強者同事又獻技 fab 指令,從官網簡介:

Fabric is a Python (2.5-2.7) library and command-line tool for streamlining the use of SSH for application deployment or systems administration tasks.

原來如此!我還活在播接時代再把玩 bash script XDD 其實之前也有試過一些同時發 ssh remote command 的工具,但悲劇收場後,就沒再用了,現在就在來吸收這套吧!

$ sudo apt-get install fabric
$ fab
Fatal error: Couldn't find any fabfiles!

Remember that -f can be used to specify fabfile path, and use -h for help.

Aborting.


是的, fab 指令會尋找當前目錄下的 fabfile.py:

$ vim fabfile.py
def hello(what):
print 'hello ' + str(what)


$ fab hello:world
hello world

Done.


非常簡潔明瞭,反正 fab 後面接的字串就是個 fabfile.py 裡定義的函數,冒號後面就是給進去的參數。接著要寫一些遠端部署指令就是寫個 function 定義一些想傳的參數,接著就愉快地寫 python 就好!可以省去用一堆 ssh target_host "remote_command" 的方式了!

$ vim fabfile.py
from fabric.api import run, task, execute, runs_once
from fabric.colors import green, magenta
import fabric.api as api

@task(default=True)
def heartbeat():
        _info("hearbeat")
run("date")

def _info(message):
        print green(message + " on %s" % api.env.host_string)

def _warn(message):
        print magenta(message + " on %s" % api.env.host_string)
$ fab
hearbeat on None
No hosts found. Please specify (single) host string for connection: localhost
[localhost] run: date
[localhost] Login password for 'user':
[localhost] out: Fri Oct 30 12:51:51 UTC 2015
[localhost] out:


Done.
Disconnecting from localhost... done.

$ fab -H localhost
[localhost] Executing task 'heartbeat'
hearbeat on localhost
[localhost] run: date
[localhost] Login password for 'user':
[localhost] out: Fri Oct 30 12:53:09 UTC 2015
[localhost] out:


Done.
Disconnecting from localhost... done.


接下來,就可以想想一連串的行為了!

[Linux] 架設私有 Yum Server 服務 @ CentOS 6.6

經強者同事的經驗傳授,對於線上服務機器應追蹤限定軟體的使用版本,可降低環境複雜度,以便偵錯。因此,學一下架設 YUM Server 來提供服務吧!

原理就是挑一台機器留個 30GB 空間,把官方的 Packages 都下載回來,接著更新其他台機器的 repo 位置即可。此例以 CentOS 6.6 x86_64 為例。

$ yum install yum-arch createrepo nginx

其中 nginx 只是為了 web server 而已,這是 CentOS yum server 架構,透過 filesytem + sqlite + http server。

$ yum install nginx
$ service nginx start
$ mkdir -p /var/www
$ ln -s /usr/share/nginx/html/ /var/www/html


接著要將資料 Yum package 都下載下來,先確認來源是不是官方版,也可以將 /etc/yum.repos.d/ 清到只剩 CentOS-Base.repo 檔案即可:

$ vim /etc/yum.repos.d/CentOS-Base.repo
[base]
name=CentOS-$releasever - Base
baseurl=http://mirror.centos.org/centos/$releasever/os/$basearch/
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-6

#released updates
[updates]
name=CentOS-$releasever - Updates
baseurl=http://mirror.centos.org/centos/$releasever/updates/$basearch/
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-6

#additional packages that may be useful
[extras]
name=CentOS-$releasever - Extras
baseurl=http://mirror.centos.org/centos/$releasever/extras/$basearch/
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-6

#additional packages that extend functionality of existing packages
[centosplus]
name=CentOS-$releasever - Plus
baseurl=http://mirror.centos.org/centos/$releasever/centosplus/$basearch/
gpgcheck=1
enabled=0
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-6

$ mkdir -p /var/www/html/centos/6/sync
$ cd /var/www/html/centos/6/sync
$ time reposync --repoid=updates --repoid=extras --repoid=base --repoid=centosplus
...
$ createrepo /var/www/html/centos/6/sync/base/
$ createrepo /var/www/html/centos/6/sync/updates/
$ createrepo /var/www/html/centos/6/sync/extras/
$ createrepo /var/www/html/centos/6/sync/centosplus/
Spawning worker 0 with ### pkgs
Workers Finished
Gathering worker results

Saving Primary metadata
Saving file lists metadata
Saving other metadata
Generating sqlite DBs
Sqlite DBs complete

$ mkdir -p /var/www/html/centos/6/updates /var/www/html/centos/6/extras/ /var/www/html/centos/6/os/ /var/www/html/centos/6/centosplus /var/www/html/centos/6/contrib
$ cd /var/www/html/centos/6/updates && ln -s ../sync/updates/ x86_64 && cd -
$ cd /var/www/html/centos/6/extras && ln -s ../sync/extras/ x86_64 && cd -
$ cd /var/www/html/centos/6/os && ln -s ../sync/base/ x86_64 && cd -
$ cd /var/www/html/centos/6/centosplus && ln -s ../sync/centosplus/ x86_64 && cd -


如此一來,搭配 web server 就可以存取這些位置:

http://public_ip/centos/6/updates
http://public_ip/centos/6/extras
http://public_ip/centos/6/os
http://public_ip/centos/6/centosplus


接著,其他 yum client 的 /etc/yum.repos.d/CentOS-Base.repo 位置更新為:

[base]
name=CentOS-$releasever - Base
baseurl=http://public_ip/centos/$releasever/os/$basearch/
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-6

#released updates
[updates]
name=CentOS-$releasever - Updates
baseurl=http://public_ip/centos/$releasever/updates/$basearch/
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-6

#additional packages that may be useful
[extras]
name=CentOS-$releasever - Extras
baseurl=http://public_ip/centos/$releasever/extras/$basearch/
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-6

#additional packages that extend functionality of existing packages
[centosplus]
name=CentOS-$releasever - Plus
baseurl=http://public_ip/centos/$releasever/centosplus/$basearch/
gpgcheck=1
enabled=0
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-6


接著在做個 yum update 後,其 packages 即可被控管使用,而製作私有的 package 時,大概就多添加個區段,並把 gpgcheck 設定成 0:

$ cat /etc/yum.repos.d/self.repo
[self]
name=SelfYumServer-$releasever
baseurl=http://public_ip/centos/$releasever/self/$basearch/
gpgcheck=0
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-6


此外,對於私有 Yum server 來說,每次變動 /var/www/html/centos/6/self/x64_86/Packages 後,都必須執行 createrepo /var/www/html/centos/6/self/x64_86/ 來更新狀態,如此一來別人就能找到。

最後,若 client 出現無法找到最新版的情況,請試試在 client server 清掉 cache,屆時重應該就會找到:

$ yum clean metadata dbcache 或 $ yum clean all

2015年10月29日 星期四

[Linux] PostgreSQL 9.4 簡易筆記 - 建立資料庫、使用者、索引 @ Ubuntu 14.04

安裝:

$ sudo apt-get install postgresql-9.4

列出已存在的資料庫:

$ sudo -u postgres psql -l
                                  List of databases
   Name    |  Owner   | Encoding |   Collate   |    Ctype    |   Access privileges
-----------+----------+----------+-------------+-------------+-----------------------
 postgres  | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 |
 template0 | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 | =c/postgres          +
           |          |          |             |             | postgres=CTc/postgres
 template1 | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 | =c/postgres          +
           |          |          |             |             | postgres=CTc/postgres
(3 rows)


建立資料庫:

$ sudo -u postgres createdb MyDB

刪除資料庫:

$ sudo -u postgres dropdb MyDB

建立使用者(-P: 建立密碼, -l: 有登入權限[預設], -L: 禁止登入, -s: 超級使用者, -d: 建立資料庫權限):

$ sudo -u postgres createuser -P -s -d -l root
$ sudo -u postgres createuser -s -d -l user1
$ sudo -u postgres createuser -s -l user2
$ sudo -u postgres createuser -l user3
$ sudo -u postgres createuser -d user4
$ sudo -u postgres createuser -s user5


列出使用者列表:

$ sudo -u postgres psql -c "SELECT * FROM pg_user";
 usename  | usesysid | usecreatedb | usesuper | usecatupd | userepl |  passwd  | valuntil | useconfig
----------+----------+-------------+----------+-----------+---------+----------+----------+-----------
 postgres |       10 | t           | t        | t         | t       | ******** |          |
 user1    |    ####1 | t           | t        | t         | f       | ******** |          |
 user2    |    ####2 | t           | t        | t         | f       | ******** |          |
 user3    |    ####3 | f           | f        | f         | f       | ******** |          |
 user4    |    ####4 | t           | f        | f         | f       | ******** |          |
 user5    |    ####5 | t           | t        | t         | f       | ******** |          |
 root     |    ####6 | t           | t        | t         | f       | ******** |          |
(7 rows)


刪除帳號:

$ sudo -u postgres dropuser user1
$ sudo -u postgres dropuser user2
$ sudo -u postgres dropuser user3
$ sudo -u postgres dropuser user4
$ sudo -u postgres dropuser user5


遠端登入資料庫(資料庫跟使用者必須先建立):

$ sudo -u postgres createdb helloworld
$ sudo -u postgres createuser -P -l user1
$ sudo -u postgres createuser -P -L user2

$ psql -h localhost -U user1
Password for user user1:
psql: FATAL:  database "user1" does not exist

$ psql -h localhost -U user1 -d helloworld
Password for user user1:
psql (9.4.4)
SSL connection (protocol: TLSv1.2, cipher: ECDHE-RSA-AES256-GCM-SHA384, bits: 256, compression: off)
Type "help" for help.

helloworld=>\q

$ psql -h localhost -U user2 -d helloworld
Password for user user2:
psql: FATAL:  role "user2" is not permitted to log in


以下皆在 helloworld 資料庫行動:

$ psql -h localhost -U user1 -d helloworld
Password for user user1:
psql (9.4.4)
SSL connection (protocol: TLSv1.2, cipher: ECDHE-RSA-AES256-GCM-SHA384, bits: 256, compression: off)
Type "help" for help.

helloworld=>


建立資料表:

helloworld=> CREATE TABLE haha ( field1 INT, field2 VARCHAR(64) );
CREATE TABLE
helloworld=> CREATE TABLE hehe ( field1 TEXT );


列出資料表:

helloworld=> \d
       List of relations
 Schema | Name | Type  | Owner
--------+------+-------+-------
 public | haha | table | user1
 public | hehe | table | user1
(2 rows)


查詢資料表定義:

helloworld=> \d haha
            Table "public.haha"
 Column |         Type          | Modifiers
--------+-----------------------+-----------
 field1 | integer               |
 field2 | character varying(64) |


刪除資料表:

helloworld=> DDROP TABLE haha;
DROP TABLE


建立索引:

helloworld=> CREATE INDEX index_test ON hehe ( field1 );
helloworld=> \d hehe
    Table "public.hehe"
 Column | Type | Modifiers
--------+------+-----------
 field1 | text |
Indexes:
    "index_test" btree (field1)


刪除索引:

helloworld=> DROP INDEX index_test;
DROP INDEX
helloworld=> \d hehe
    Table "public.hehe"
 Column | Type | Modifiers
--------+------+-----------
 field1 | text |


建立 Partial Indexes:

helloworld=> CREATE INDEX index_substring ON hehe ( substring(field1, 0, 32) );
CREATE INDEX
helloworld=> CREATE INDEX index_condition ON hehe ( field1 )
helloworld->  WHERE substring(field1, 0, 1) = 'a' ;
CREATE INDEX
helloworld=> \d hehe
    Table "public.hehe"
 Column | Type | Modifiers
--------+------+-----------
 field1 | text |
Indexes:
    "index_condition" btree (field1) WHERE "substring"(field1, 0, 1) = 'a'::text
    "index_substring" btree ("substring"(field1, 0, 32))


從 STDIN 輸入資料至 helloworld.hehe 中:

$ bash --version
GNU bash, version 4.3.30(1)-release (x86_64-pc-linux-gnu)
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>

This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

$ cat <<EOF | psql -h localhost -U user1 -W -d helloworld
> COPY hehe (field1) FROM stdin;
> 1
> 2
> 3
> 4
> 5
> 6
> EOF
Password for user user1:
COPY 6

$ psql -h localhost -U user1 -W -d helloworld -c 'SELECT * FROM hehe;'
Password for user user1:
 field1
--------
 1
 2
 3
 4
 5
 6
(6 rows)

2015年10月27日 星期二

透過 Google Analytics - Measurement Protocol 追蹤 IOT、Email 開信率等

雖然很多東西都建立在 Android 上,但總是有純 Unix 的環境,這時就用用 Google analytics (GA) 的 REST API 了 XD 這東西用途很廣,因為它可以偽裝成 image ,例如 <img src="//www.google-analytics.com/collect?...">,甚至可以用在 EDM 等等的(雖然 Email 常常預設把遠端資源關閉) ,此例,我們專注在 IOT 上,而測試方式只要用用 cURL 即可,十分便利。

由於是 IOT 角色,須留意 GA 的資源限制:https://developers.google.com/analytics/devguides/collection/protocol/v1/limits-quotas

  • 10 million hits per month per tracking ID
  • 200,000 hits per user per day
  • 500 hits per session not including ecommerce (item and transaction hit types).

總之,用法都很簡單,叫 IOT 定期打卡即可,最重要的工作項目反而是定義產品的使用情境,把那些狀態定義好後,當作 web page 來呼叫 Google Analytics API 吧!

簡易範例:

$ curl 'https://www.google-analytics.com/collect?v=1&t=screenview&tid=TRACKING_ID&an=YOUR_APP_NAME&cid=CLIENT_ID&cd=YOUR_PRODUCT_STATE'
GIF89a?????


其中範例回應的就是一張 GIF 圖檔,而更多應用請參考 https://developers.google.com/analytics/devguides/collection/protocol/v1/parameters ,若一直試不出來,可以用 https://ga-dev-tools.appspot.com/hit-builder/ 偵錯看看。