Jex’s Note

Netstat 指令

常用

  • -t: tcp
  • -u: udp
  • -n: don’t resolve names
  • -l: listening
  • -p: show pid or program name
  • -i: Display a table of all network interfaces.
  • -a: Show both listening and non-listening sockets.
  • 如果 netstat / lsof 無法顯示出 pid or program name 要改用 sudo 執行

列出在監聽的網路服務:

netstat -tunl

列出所有的連線

netstat -antp

列出已連線的網路連線狀態:

netstat -tun

刪除已建立或在監聽當中的連線:

netstat -tunp   #看他的pid ex: 10270
kill -9 10270

netstat -nltp

查看 port 被那隻程式佔用

lsof -i :3306

查看有些建立連線 (4 stands for ipv4)

lsof -i 4

查看某個 process 建立的連線

lsof -p 12084

找出哪個 pid 開啟某個特定的檔案

lsof -t /tmp/qq.log

Show process name, pid and port

$ lsof -i -n -P | grep TCP
Spotify   60924  jex   47u  IPv4 0x5f4ad82c61e46fc7      0t0  TCP 127.0.0.1:4381 (LISTEN)
Spotify   60924  jex   48u  IPv4 0x5f4ad82c620734df      0t0  TCP 127.0.0.1:4371 (LISTEN)

顯示 timer

$ netstat -antop

tcp        0      0 0.0.0.0:55206           0.0.0.0:*               LISTEN      -                off (0.00/0/0)
tcp        0      0 10.173.27.211:11211     0.0.0.0:*               LISTEN      -                off (0.00/0/0)
tcp        0      0 0.0.0.0:111             0.0.0.0:*               LISTEN      -                off (0.00/0/0)
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      -                off (0.00/0/0)
tcp        0      0 182.92.229.142:40879    110.75.102.62:80        ESTABLISHED -                off (0.00/0/0)
tcp        0      0 10.173.27.211:58364     10.171.39.175:22        TIME_WAIT   -                timewait (15.42/0/0)
tcp        0      0 182.92.229.142:22       125.227.251.150:51042   ESTABLISHED -                keepalive (5318.20/0/0)
tcp        0      0 182.92.229.142:22       125.227.251.150:56130   ESTABLISHED -                keepalive (5187.13/0/0)
tcp        0      0 10.173.27.211:2049      10.171.39.175:825       ESTABLISHED -                off (0.00/0/0)
tcp        0      0 10.173.27.211:52061     10.242.174.13:80        TIME_WAIT   -                timewait (48.05/0/0)
tcp        0      0 10.173.27.211:2049      10.170.189.142:696      ESTABLISHED -                off (0.00/0/0)
tcp6       0      0 :::56705                :::*                    LISTEN      -                off (0.00/0/0)
tcp6       0      0 :::2049                 :::*                    LISTEN      -                off (0.00/0/0)

顯示連線狀態數量

$ netstat -an|awk '/tcp/ {print $6}'|sort|uniq -c

     16 CLOSING
    130 ESTABLISHED
    298 FIN_WAIT1
     13 FIN_WAIT2
      9 LAST_ACK
      7 LISTEN
    103 SYN_RECV
   5204 TIME_WAIT

狀態: 描述

  • ESTABLISHED: The socket has an established connection.
  • SYN_SENT: The socket is actively attempting to establish a connection.
  • SYN_RECV: A connection request has been received from the network.
  • FIN_WAIT1: The socket is closed, and the connection is shutting down.
  • FIN_WAIT2: Connection is closed, and the socket is waiting for a shutdown from the remote end.
  • TIME_WAIT: The socket is waiting after close to handle packets still in the network.
  • CLOSE: The socket is not being used.
  • CLOSE_WAIT: The remote end has shut down, waiting for the socket to close.
  • LAST_ACK: The remote end has shut down, and the socket is closed. Waiting for acknowledgement.
  • LISTEN: The socket is listening for incoming connections.
  • CLOSING: Both sockets are shut down but we still don’t have all our data sent.
  • UNKNOWN: The state of the socket is unknown.

https://i.stack.imgur.com/5H0Cr.png

大量 TIME_WAIT 問題

(..略..)
tcp        0      0 127.0.0.1:9000              127.0.0.1:37260             TIME_WAIT   -
tcp        0      0 10.0.11.229:58492           10.0.23.32:3306             TIME_WAIT   -
(..略..)

問題 :

php-fpm 使用 9000 port, mysql 使用 3306 如果一個 request 進來最少就會有兩個 TIME_WAIT,要等系統 1 分鐘才會回收,在這期間就佔用了兩個 TCP 連線, 如果 request 量大的時候就會沒 port 可用造成錯誤

產生原因

ref : 打開linux-tcp端口快速回收

  1. nginx現有的負載均衡模塊實現php fastcgi負載均衡,nginx使用了短連接方式,所以會造成大量處於TIME_WAIT狀態的連接。
  2. TCP/IP設計者本來是這麼設計的, 主要有兩個原因
    • 防止上一次連接中的包,迷路後重新出現,影響新連接(經過2MSL,上一次連接中所有的重複包都會消失)
    • 可靠的關閉TCP連接, 在主動關閉方發送的最後一個ack(fin) ,有可能丟失,這時被動方會重新發fin, 如果這時主動方處於CLOSED 狀態,就會響應rst 而不是ack。所以主動方要處於TIME_WAIT 狀態,而不能是CLOSED 。

解決方法 : 開啟 Linux TCP port 快速回收

修改 /etc/sysctl.conf, 但重啟後會還原(?)

net.ipv4.tcp_tw_reuse = 1                   # Allow to reuse TIME-WAIT sockets for new connections when it is safe from protocol viewpoint. Default value is 0.  It should not be changed without advice/request of technical experts.
net.ipv4.tcp_tw_recycle = 1                 # Enable fast recycling TIME-WAIT sockets. Default value is 0.  It should not be changed without advice/request of technical experts.

再執行 sudo sysctl -p 生效

注意!! 修改 tcp_tw_recycle 在使用 load balancer 可能會造成問題 ref : 記一次TIME_WAIT網絡故障 下面別人的回覆訂正原文錯誤也值得一看

結果

當 request 一執行完畢 TIME_WAIT 只會存在一下子就消失了

TIME_WAIT 補充

TCP is layer 4, HTTP layer 7.

In HTTP 1.0, HTTP Keep-Alive is used at layer 7 to simulate persistent connections using Connection header.

In HTTP 1.1, connections are assumed persistent by default and then rely on TCP only to do that job. Requests can be pipelined in the same TCP connection, then one side will set Connection: close in the last request or response headers, so both side knows that no more HTTP request can be exchanged and the connection will then be closed.

Usually in the case of a web server, the TIME_WAIT state will be the state after which, once decided to actively close the connection, it received client’s FIN packet and is sending the last ACK back in the four-way tear-down. After this, it waits for 2 * MSL : it’s a way to be sure that the connection is closed. That’s where the 60s compiled in the kernel comes from. In this way we are sure that we won’t receive in a new connection, using the same 4 tuple, packets out of sequence arising from the previous connection.

You don’t want to change it.

In the other side server.max-keep-alive-idle is the timeout after which an ESTABLISHED connection will be considered idle if no HTTP request comes in and will be actively closed by the web server. When this decision is made, as you understand now, the TCP tear-down will take place.

Be very careful with tcp_tw_recycle, if your visitors come from behind a wide NATed network then it could lead to multiple TCP connections with the same 4 tuple taking place with out of order timestamps resulting in silently dropping client connections attempts on the server side.

So the best option is to adjust the parameter you saw in lighttpd. System-wide, you can safely lower FIN_WAIT2 state and raise buckets for sockets in TIME_WAIT state with net.ipv4.tcp_fin_timeout and net.ipv4.tcp_max_tw_buckets.

其他指令

netstat command example to find out gateway/router IP

netstat -r -n

or

route
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
default         192.168.79.xxx  0.0.0.0         UG    0      0        0 em1
192.168.79.0    *               255.255.255.128 U     0      0        0 em1

顯示主機上所有已建立的連線 (己開放的port)

netstat -na

顯示所有 port 80 的連線,並把結果排序。

netstat -an | grep :80 | sort

列出主機上有多少個 SYNC_REC,一般上這個數字應該相當低。

netstat -n -p|grep SYN_REC | wc -l

同樣是列出 SYNC_REC,但不只列出數字,而是將每個 SYNC_REC 的連線列出。

netstat -n -p | grep SYN_REC | sort -u

列出發送 SYNC_REC 的所有 ip 地址。

netstat -n -p | grep SYN_REC | awk ‘{print $5}’ | awk -F: ‘{print $1}’

計算每一個 ip 在主機上建立的連線數量。

netstat -ntu | awk ‘{print $5}’ | cut -d: -f1 | sort | uniq -c | sort -n

列出從 TCP 或 UDP 連線到主機的 ip 的數量。

netstat -anp |grep ‘tcp\|udp’ | awk ‘{print $5}’ | cut -d: -f1 | sort | uniq -c | sort -n

列出每個 ip 建立的 ESTABLISHED 連線數量。

netstat -ntu | grep ESTAB | awk ‘{print $5}’ | cut -d: -f1 | sort | uniq -c | sort -nr

列出每個 ip 建立的 port 80 連線數量。

netstat -plan|grep :80|awk {‘print $5′}|cut -d: -f 1|sort|uniq -c|sort -nk 1

ref: http://www.hkcode.com/linux-bsd-notes/559

Windows 安裝 Gcc 編譯器 - MinGW

MinGW 介紹

MinGW 全稱 Minimalist GNU For Windows,是個精簡的Windows平台C/C++、ADA及Fortran編譯器,相比Cygwin而言,體積要小很多,使用較為方便。MinGW提供了一套完整的開源編譯工具集,以適合Windows平台應用開發,且不依賴任何第三方C運行時庫。

MinGW包括:

  • 一套集成編譯器,包括C、C++、ADA語言和Fortran語言編譯器
  • 用於生成Windows二進製文件的GNU工具的(編譯器、鏈接器和檔案管理器)
  • 用於Windows平台安裝和部署MinGW和MSYS的命令行安裝器(mingw-get)
  • 用於命令行安裝器的GUI打包器(mingw-get-inst)

下載 MinGW

mingw 下載頁面 上面應該有可以直接下載最新版的連結


Looking for the latest version? Download mingw-get-setup.exe (86.5 kB)


安裝套件 - C/C++ 編譯器

安裝完後會跳出一個視窗讓你選擇你要安裝的套件,

mingw32-gcc-g++ 上按右鍵選擇 Mark for Installation 把它勾選起來

gc  .JPG

然候左上角 Installation 選擇 Apply Change 就會開始安裝 C/C++ 編譯器了,

設定系統環變數

安裝完後要將 GCC 的路徑 C:\MinGW\bin 加到系統環境變數 PATH, 才能使用,

我的電腦右鍵 -> 內容 -> 進階系統設定 -> 進階TAB, 點選在下面的環境變數 -> 在下面的系統變數那新增


變數名稱 : PATH 變數值 : %SystemRoot%\system32;%SystemRoot%;C:\MinGW\bin


重開機, 讓變數生效

測試是否安裝完成

可以在 cmd 輸入 gcc -v, 如果出現 gcc 的相關資訊表示安裝成功!

gccVersion.JPG

windows 8

如果 windows 8 安裝完 MinGW 是沒有 C:\MinGW\bin\gcc.exe 而是 C:\MinGW\bin\g++.exe

所以 cmd 指令要改下 g++ -v

Compile C++ 檔案

C:\MinGW 下新增 hello.cpp :

#include <iostream>  // Basic input and output library
#include <cstdlib>   // system("pause")

using namespace std;

int main()
{
    cout << "Hello World" << endl;
    system("pause");
    return 0;
}

cmd :

cd C:\MinGW
g++ hello.cpp -o hello.exe

cc1plus.exe - 系統錯誤

無法啟動程式,因為您的電腦遺失 libgmp-10.dll。請嘗試重新安裝以修正這個問題。

error.PNG

再打開安裝檔 MinGW Installation Manager 或 C:\MinGW\bin\mingw-get.exe, 他們是一樣的東西

然候再安裝 mingw32-base, 即可解決此問題

install mingw32-base.PNG

ref: MinGW windows go mingw c

Raspberry Pi 作業系統, XBMC 影音, Samba 網芳

介紹

raspberry-pi.jpg

Raspberry Pi 是一台小型的電腦, 幾乎一般 linux 電腦能做到的事它也都能做到, 而它最大的優勢就是體型非常的小, 小到你可以方便攜帶, 而功能一點也不陽春, 非常適合拿它來作媒體中心或小型的運算。

如果還沒有 Raspberry Pi(以下簡稱 rpi) 不知道哪些要買的可以參考本文末的推薦清單

安裝 OS(作業系統)

[下載 OS 映像檔]

下載 Raspberry Pi 的 OS 選擇 Raspbian 版本是 wheezy

下載完後解壓縮出來是一個 2013-09-25-wheezy-raspbian.img 檔

[將 Raspbian OS 燒錄到 SD 卡]

不同的作業系統要用不同的方式燒到 SD 卡, 先將 SD 卡插入到電腦

如果是 Windows 下載 Win32 Disk Imager, 解壓縮完是一個資料夾, 執行 Win32DiskImager, Image File 選擇 2013-09-25-wheezy-raspbian.img

Device 選擇 SD 卡, 按 write, 就會進行燒錄了

[安裝 Raspbian]

將燒錄好的 SD 卡插入 Raspberry pi, 並且將電源線插上插座, 鍵盤接上, HDMI線接上電視或電腦螢幕,

就可以開始使用了,基本上 SD 卡燒進去的檔案已安裝的差不多了, 剩下的只是一些設定的調整,

例如第一項是檢查你的 SD 卡有沒有讓整個 OS 使用, 還有修改密碼的設定, 其他的可以不用設定直接跳過


如果像我一樣接上螢幕沒有畫面, 試試看 rpi 把 SD 卡拔出來再插到你的電腦, 打開 SD 卡的 config.txt 並加上 :

sdtv_mode = 0
sdtv_aspect = 3
hdmi_group = 1
hdmi_mode = 1
sdtv_aspect=3  16:9

再插回 rpi 開機後螢幕應該就會有畫面了


  • Raspberry Config GUI : sudo raspi-config
  • 預設帳密 : pi/raspberry

安裝 Raspbmc (也就是 Raspberry 版的 XBMC)

跟作業系統一樣下載完要燒到 SD 卡裡, 點我下載

所以要安裝前先關機, 將 SD 卡從 rpi 拔下來, 然候再插到你的電腦,

接著打開剛剛下載的軟體, 在上面選擇你的 SD 卡位置, 及下面打勾 Install Raspbmc to a USB drive 將 raspbmc 燒進 SD 卡

然候再把 SD 卡插到 rpi, 如果有接上螢幕開機後就會自動安裝, 並且進入到 XBMC 畫面了


如果發生錯誤: Raspbmc cannot be installed to a USB drive, because it cannot detect it!

將 SD 卡插到你電腦然候檢查 SD 卡有沒有檔名叫做 usb 的檔案, 有的話刪除它, 再重新插回 rpi 啟動就能自動安裝了


[搖控 XBMC 的方式]

Remote default port : 9090, 如果有設定防火牆要記得打開 9090 port

[瀏覽器] :

Chrome extension 安裝 XBMC

先用鍵盤在 XBMC 操控, 因為要開啟遠端遙控, 才可以用 chrome 的 extension 控制

系統設定 -> 服務 -> 遠端遙控 -> 允許其他電腦連接

在開啟 chrome 的 extenstion -> IP 輸入 rpi 的 ip (如果不知道可以到 系統設定 -> 系統資訊 看 ip 是什麼,

[手機] :

手機用 wifi 連到家裡的無線網路 (為了要跟 rpi 同一個 lan 下)

下載 Official XBMC Remote 這個 app, IP 輸入後就可以操控了

[操作界面]

滑鼠操作

system -> settings -> appearance -> skin 改為 `Touched`

鍵盤操作

system -> settings -> appearance -> skin 改為 `Raspbmc Confluence Mod`

[XBMC 中文語系]

如果亂碼, 有些操作的項目根本無法顯示, 跟著以下操作至少能切回英文

system -> settings(第一項) -> appearance(第一項) -> International(第二項) -> Language 改為 `English(US)`

改成中文語系前先將 Fonts 由 Skin Default 改為 Arial based 才不會改了中文後就變成亂碼了

system -> settings -> appearance -> skin -> Fonts 改為 `Arial Based`

改成中文語系

system -> settings -> appearance -> international -> Language 改為 Chinese(Tranditional)

[XBMC 指令]

  • sudo initctl start xbmc
  • sudo initctl stop xbmc
  • sudo initctl restart xbmc

[用 XBMC 看線上影片(ex: PPS)]

[下載觀看線上影片的套件]

xbmc-addons-chinese 選擇 repository.googlecode.xbmc-addons-chinese-eden.zip 複製連結網址

下載到 rpi 裡

cd /tmp
wget https://xbmc-addons-chinese.googlecode.com/files/repository.googlecode.xbmc-addons-chinese-eden.zip

在下載時會發現有分 eden 與 Dharma 版, 它們是指版本代號, Dharma 是 10, eden 是 11

像我的是 12.2 版, 安裝 eden 沒問題

如果要查看 XBMC 版本 : XBMC 啟動後 -> 系統設定 -> 糸統資訊 就會顯示你的 XBMC 版本


[安裝套件]

系統設定 -> 附加元件 -> 從 zip 檔案安裝 -> 檔案系統 -> 剛是下載到 /tmp 所以選擇 /tmp -> repository.googlecode.xbmc-addons-chinese-eden.zip

[啟用你想開啟的服務 (ex: pps)]

系統設定 -> 附加元件 -> 取得附加元件 -> 全部附加元件 -> 視訊附加元件 -> 往下找 PPStream (最下面是中文的服務, 騰訊視頻等等)

  • 撥放含有字幕檔的影片也沒有問題, 將 XXX.mkv XXX.srt 放在同一個目錄, 撥放時 XBMC 自動會載入字幕
  • 不支援 .rmvb 的檔, 播放時只會有聲音不會有畫面

[從 XBMC 回到 terminal]

在 XBMC 的介面左下角有電源的 icon, 點它並選擇第一個 “關閉”, 然候再按 esc, 就

可以回到 terminal 介面了

ctrl+alt+F1 似乎也行(沒試過)

安裝及設定 samba

如果 windows 要丢檔案到 rpi 裡就可以透過 samba, 例如把影片丢進去再使用 XBMC 播放在電視上看

參考 samba 安裝

\\192.168.74.65\share), 安裝完後在 /home/pi 下建立資料夾 samba

/etc/samba/smb.conf 最下面加入

[samba]
    path = /home/pi/samba
    public = yes
    writable = yes
    printable = no

重啟

sudo service samba restart
  • 如果有設定防火牆記得開 445 port
  • 網址 : \\192.168.1.10\samba

設定無線網路

ifconfig -a 看有沒有 wlan0, 這個就是你的無線網卡, 如果沒有執行 lsusb 看 usb 的無線網卡有讀到嗎?

pi@raspbmc:~$ lsusb
Bus 001 Device 002: ID 0424:9512 Standard Microsystems Corp.
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 001 Device 003: ID 0424:ec00 Standard Microsystems Corp.
Bus 001 Device 004: ID 0bda:8176 Realtek Semiconductor Corp. RTL8188CUS 802.11n WLAN Adapter

這是我的 usb 無線網卡 : RTL8188CUS 802.11n WLAN Adapter

如果都有確定有讀到就可以開始設定無線網路了, 可參考設定無線網路

推薦購買的清單 :

Raspberry pi 主機板 Model B (512mb) : $1390

另一個版本 Model A(256mb), 硬體相對較小, usb 插槽只有一個

壓克力外殼(6片裝密合式) + 3個散熱片 : $100

另一種是開放式的, 上下各一片壓克力, 4 個角落以柱子固定

電源(5V2A, micro usb 線) : $100

建議買, 否則就得用電腦透過 usb 線供電給主機板

8GB SD卡 : $200

必買! 對 Raspberry Pi 來說, 它就相當於一般電腦的硬碟

Mini wifi 無線網卡(802.11N) : $200

  • 注意! 網卡需與主機版相容
  • 非必要買, 可直接用網路線接主機版

HDMI v1.4 傳輸線 : $100

如果要輸出到電視上看, 而且電視也支授 HDMI 的話就要買

USB PC 搖控器 : $200

建議買, 不然就得接鍵盤到主機板或者透過 chrome extension - xbmc 才能操作 XBMC

Q & A

鍵盤輸入某些符號(ex: #, @)keycode錯亂

sudo dpkg-reconfigure keyboard-configuration

選擇 Generic 105-key (Intl) PC -> 裡面的選項都是 UK , 所以選擇 Other -> English (US) -> layout, 選擇 English (US) -> The default for the keyboard layout (default) -> No compose key (default) -> 組合鍵 X server, 選擇 Yes

重開機

sudo shutdown -r now

Wireless Network

安裝 wpa client

sudo apt-get install wireless-tools wpasupplicant

掃描無線網路

sudo iwlist wlan0 scan | grep SSID
                    ESSID:"hinet-net4690695"
                    ESSID:"BUFFALO-E05EE0"
                    ESSID:"BUFFALO-E05EE0-1"
                    ESSID:"kking22"
                    ESSID:"TP-LINK_5499B2"
                    ESSID:"HTC ONE X - Jex"
                    ESSID:"P880"

等等要將 SSID 填入 /etc/network/interfaces wpa-ssid 的值

新增 /etc/network/interfaces :

auto lo
iface lo inet loopback

auto eth0
iface eth0 inet dhcp


auto wlan0
allow-hotplug wlan0
iface wlan0 inet dhcp
wpa-ssid My-Hone-Wireless
wpa-psk My-Password
  • SSID 就是無線網路的名稱
  • WPA-PSK金鑰 就是無線網路的密碼

重新啟動無線網路介面

sudo ifdown wlan0
sudo ifup wlan0

成功連線的結果 :

pi@raspbmc:~$ sudo ifdown wlan0
ifdown: interface wlan0 not configured
pi@raspbmc:~$ sudo ifup wlan0
ioctl[SIOCSIWAP]: Operation not permitted
ioctl[SIOCSIWENCODEEXT]: Invalid argument
ioctl[SIOCSIWENCODEEXT]: Invalid argument
Internet Systems Consortium DHCP Client 4.2.2
Copyright 2004-2011 Internet Systems Consortium.
All rights reserved.
For info, please visit https://www.isc.org/software/dhcp/

Listening on LPF/wlan0/00:0b:81:84:7a:17
Sending on   LPF/wlan0/00:0b:81:84:7a:17
Sending on   Socket/fallback
DHCPDISCOVER on wlan0 to 255.255.255.255 port 67 interval 4
DHCPDISCOVER on wlan0 to 255.255.255.255 port 67 interval 11
DHCPREQUEST on wlan0 to 255.255.255.255 port 67
DHCPOFFER from 192.168.1.1
DHCPACK from 192.168.1.1
Reloading /etc/samba/smb.conf: smbd only.
bound to 192.168.1.10 -- renewal in 38644 seconds.

以下是我實體網路線及無線網路都有連線的結果

pi@raspbmc:~$ ifconfig
eth0      Link encap:Ethernet  HWaddr b8:27:eb:7e:6e:3f
          inet addr:192.168.1.236  Bcast:192.168.1.255  Mask:255.255.255.0
          inet6 addr: fe80::ba27:ebff:fe7e:6e3f/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:3168 errors:0 dropped:0 overruns:0 frame:0
          TX packets:2190 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:443833 (433.4 KiB)  TX bytes:375591 (366.7 KiB)

lo        Link encap:Local Loopback
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:8 errors:0 dropped:0 overruns:0 frame:0
          TX packets:8 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:480 (480.0 B)  TX bytes:480 (480.0 B)

wlan0     Link encap:Ethernet  HWaddr 00:0b:81:84:7a:17
          inet addr:192.168.1.10  Bcast:192.168.1.255  Mask:255.255.255.0
          inet6 addr: fe80::20b:81ff:fe84:7a17/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:28 errors:0 dropped:2179 overruns:0 frame:0
          TX packets:51 errors:0 dropped:3 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:31439 (30.7 KiB)  TX bytes:36803 (35.9 KiB)

其他

如果將無線網路登入設定寫在 interfaces 裡面的一些設定寫法

/etc/network/interfaces 的寫法 :

wpa-scan-ssid 1
wpa-ap-scan 1
wpa-key-mgmt WPA-PSK
wpa-proto RSN WPA
wpa-pairwise CCMP TKIP
wpa-group CCMP TKIP
wpa-ssid "My Secret SSID"
wpa-psk "My SSID PSK"

另外一種連線設定, 使用 wpa_supplicant

/etc/network/interfaces :

auto lo

iface lo inet loopback
iface eth0 inet dhcp

allow-hotplug wlan0
iface wlan0 inet manual
wpa-roam /etc/wpa_supplicant/wpa_supplicant.conf
iface default inet dhcp

/etc/wpa_supplicant/wpa_supplicant.conf 新增(沒有的話建立)

完整寫法 :

ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1

network={
  ssid="wireless_1"                                                     // 無線網路的名稱
  #scan_ssid=1
  proto=WPA RSN
  key_mgmt=WPA-PSK
  pairwise=CCMP TKIP
  group=CCMP TKIP
  psk=ec8cdd1c0aa2ebcc6564ee81587ebad81e4a39ebf6c4265e3f931175e3926c5b  // 無線網路的密碼(加密後) 寫法1
  # psk="my_password"   // 無線網路的密碼(未加密) 寫法2
}

偷懶寫法 :

network={
  ssid="TP-LINK_34403E"
  psk="2734403E"
  id_str="home"
}
network={
  ssid="jx"
  psk="00000000"
  id_str="my mobile"
}

不將明碼打在設定檔上, 使用加密後的密碼在設定檔裡較為安全

$ wpa_passphrase jex_ssid jex_password
network={
        ssid="jex_ssid"
        #psk="jex_password"
        psk=fce88e792dea2299472529eea209012a812cda28cbbf540e2a55d45be98988d0
}

加密協定

  • TKIP 與 CCMP 為安全加密協定
  • 有些無線網路設備以 AES 或 AES-CCMP 來表示 CCMP
  • AES 效能更好, 主流, 安全, 美國主推, 在 wifi 上用來取代 TKIP, 雙向加密解密

監聽封包

Tcpdump

監聽封包

sudo tcpdump -i lo -nn port 8080
13:45:48.703124 IP 127.0.0.1.42893 > 127.0.0.1.8080: Flags [S], seq 2569649818, win 43690, options [mss 65495,sackOK,TS val 2431608 ecr 0,nop,wscale 6], length 0
13:45:48.703130 IP 127.0.0.1.8080 > 127.0.0.1.42893: Flags [S.], seq 986657362, ack 2569649819, win 43690, options [mss 65495,sackOK,TS val 2431608 ecr 2431608,nop,wscale 6], length 0
13:45:48.703137 IP 127.0.0.1.42893 > 127.0.0.1.8080: Flags [.], ack 1, win 683, options [nop,nop,TS val 2431608 ecr 2431608], length 0
13:45:48.703572 IP 127.0.0.1.42893 > 127.0.0.1.8080: Flags [P.], seq 1:29, ack 1, win 683, options [nop,nop,TS val 2431608 ecr 2431608], length 28
13:45:48.703580 IP 127.0.0.1.8080 > 127.0.0.1.42893: Flags [.], ack 29, win 683, options [nop,nop,TS val 2431608 ecr 2431608], length 0
13:45:48.703824 IP 127.0.0.1.42893 > 127.0.0.1.8080: Flags [P.], seq 29:39, ack 1, win 683, options [nop,nop,TS val 2431608 ecr 2431608], length 10
13:45:48.703830 IP 127.0.0.1.8080 > 127.0.0.1.42893: Flags [.], ack 39, win 683, options [nop,nop,TS val 2431608 ecr 2431608], length 0
13:45:48.704009 IP 127.0.0.1.42893 > 127.0.0.1.8080: Flags [F.], seq 39, ack 1, win 683, options [nop,nop,TS val 2431609 ecr 2431608], length 0
13:45:48.743612 IP 127.0.0.1.8080 > 127.0.0.1.42893: Flags [.], ack 40, win 683, options [nop,nop,TS val 2431619 ecr 2431609], length 0

監聽封包內容

sudo tcpdump -i lo -nn port 8080 -X
(...略...)
13:42:53.139609 IP 127.0.0.1.8080 > 127.0.0.1.42892: Flags [.], ack 40, win 683, options [nop,nop,TS val 2387718 ecr 2387708], length 0
        0x0000:  4500 0034 f30e 4000 4006 49b3 7f00 0001  E..4..@.@.I.....
        0x0010:  7f00 0001 1f90 a78c 0cc5 9df7 37a2 5c73  ............7.\s
        0x0020:  8010 02ab fe28 0000 0101 080a 0024 6f06  .....(.......$o.
        0x0030:  0024 6efc                                .$n.

監聽 post, 並且輸出成好閱讀模式

sudo tcpdump -s 0 -A 'tcp dst port 80 and (tcp[((tcp[12:1] & 0xf0) >> 2):4] = 0x504f5354)' -i eth0
(...略...)
E....   @.@..8..Of6......P.N$.Y...P..:....POST /oauth/authorize?client_id=a216481c HTTP/1.1
User-Agent: curl/7.22.0 (x86_64-pc-linux-gnu) libcurl/7.22.0 OpenSSL/1.0.1 zlib/1.2.3.4 libidn/1.23 librtmp/2.3
Host: example.com
Accept: */*
Content-Length: 8
Content-Type: application/x-www-form-urlencoded

(tcp[((tcp[12:1] & 0xf0) >> 2):4] = 0x504f5354) 是監聽 post 的意思

如何使用 tcpdump 監聽 (1)來自 eth0 介面卡且 (2)通訊協定為 port 22 ,(3)封包來源為 192.168.1.101 的封包資料?

tcpdump -i eth0 -nn -l 'port 22 and src host 192.168.1.101'

參數

  • -i: 後面接要『監聽』的網路介面,例如 eth0, lo, ppp0 等等的介面;
  • -nn: 直接以 IP 及 port number 顯示,而非主機名與服務名稱
  • -X: 可以列出十六進位 (hex) 以及 ASCII 的封包內容,對於監聽封包內容很有用
  • -l: 使用標準輸出的 buffer, 顯示上比較即時

Ngrep

聽 GET/POST/PUT 80 port

sudo ngrep -W byline -d eth0 -t '^(GET|POST|PUT)' 'port 80'

聽 GET/POST/PUT 特定 host 的 80 port

sudo ngrep -d eht0 -t '^(GET|POST|PUT)' "src host example.com and port 80"

聽 GET/POST/PUT 特定 host 的 80 port, TCP 協定

sudo ngrep -t '^(GET|POST|PUT)' "src host example.com and tcp and dst port 80"

其他

ref: ngrep cheat sheet

Print udp packets

ngrep '' udp

Print packets passing eth0 device. Without -d ngrep listens to a default interface. ngrep -d eth0 Print packets for port 80 regardless of device

ngrep -d any port 80

Only print packets that contain “interesting-domain.com”

ngrep -d any “interesting-domain.com” port 80

You can use regex such as ‘.*’ in the search string

ngrep -d any “domain-.*.com” port 80

Or use regex to search for ‘pass’ or ‘USER’

ngrep -d any “pass|USER” port 80

And ignore case with -i to match for ‘user’ as well

ngrep -d any -i “pass|USER” port 80

If you’re logged in via SSH you might want to ignore your own traffic

ngrep -d any port not 22

Only print packet headers and payload (if relevant)

ngrep -q -d any “needle” port 80

Use -W byline for more readable output

ngrep -d any -W byline “needle” port 80

Limit the number of results with -n

ngrep -d any “needle” -n 3 port 80

Print empty packets with -e

ngrep -e -d any “needle” port 80

Xargs 指令

介紹

build and execute command lines from standard input

用法

假設有個檔案結構如下 :

$ tree test
test
├── c1
│   ├── ii.del
│   └── pp.ext
├── c2
│   ├── gg.del
│   └── hh.ext
└── c3
    ├── c3-1
    │   ├── qq.del
    │   └── xx.ext
    ├── cc.ext
    └── ff.del

4 directories, 8 files

如果我要刪除 test 下所有 *.del 的檔案

找出 *.del

$ find test -name "*.del"
test/c3/ff.del
test/c3/c3-1/qq.del
test/c2/gg.del
test/c1/ii.del

加上 xargs 指令, 可以一次幫你把找到的結果刪除

$ find test -name "*.del" | xargs rm

如果前面 find 那邊沒有任何結果輸出會出現錯誤訊息

rm: missing operand
Try 'rm --help' for more information.

可加上 --no-run-if-empty 來避免 :

$ find test -name "*.del" | xargs --no-run-if-empty rm

--no-run-if-empty or -r : If the standard input does not contain any nonblanks, do not run the command. Normally, the command is run once even if there is no input. This option is a GNU extension.

將筆對到的字串暫存成符號供取代使用, linux supports -i, mac supports -I

mac

redis-cli KEYS "user:???" | xargs -I@ redis-cli HSET @ field1 1

linux

redis-cli KEYS "user:???" | xargs -i@ redis-cli HSET i field1 1

Add file extension

$ tree .
.
├── cc
└── qq

$ ls | xargs -I file mv file file.txt && ls
cc.txt  qq.txt

不用 xargs 且達到一樣效果 :

$ for i in `ls`;do mv $i ${i}.txt; done && ls
cc.txt  qq.txt
  • xargs :
  • -I replace-str
  •  Replace occurrences of replace-str in the initial-arguments with names read from  standard  input.
    
  •  Also,  unquoted  blanks  do  not  terminate  input  items;  instead  the  separator is the newline
    
  •  character.  Implies -x and -L 1.
    

Change file extension

change xxx.thml -> xxx.txt

ls | grep html | sed 's/.html//g' | xargs -I file mv file.html file.txt

Add prefix

ls | xargs -I {FILE} mv {FILE} prefix_{FILE}

{FILE} 是自訂讓 xargs 辨識用的變數名稱

Example

將指到的檔都刪除

find -name "*.bak" | xargs rm

如果沒有找到也不要噴出錯誤訊息

find -name "*.bak" | xargs --no-run-if-empty rm

ref : http://blog.yam.com/ddy1280/article/13941218

Nmap 指令

介紹

有時候你想知道該網域下有哪些 ip 正在使用或有哪些 port 是開放的, 就可以使用 nmap 來檢查

安裝

ubuntu :

sudo apt-get install nmap

使用

假如已經有確定的 port 想知道是否開放可直接用 telnet nc

telnet xxx.oo 8010

$ nc -zv test-db.c6c8mn7tsdgv0.us-west-2.rds.amazonaws.com 3306
Connection to test-db.c6c8mn7tsdgv0.us-west-2.rds.amazonaws.com 3306 port [tcp/mysql] succeeded!
  • -z: Specifies that nc should just scan for listening daemons, without sending any data to them. It is an error to use this option in conjunction with the -l option.
  • -v: Have nc give more verbose output.

-sP 掃網段下有使用的 ip

nmap -sP 192.168.1.0/24

or

nmap -sP 192.168.1.1-254

-sT : TCP connect 掃描(Port Scanning)

這是對 TCP 的最基本形式的偵測,直接連到目標主機進行埠掃描並完成一個完整的三次交握過程 (SYN, SYN/ACK, ACK),但因為服務器接受了一個連接但它卻馬上斷開,於是其記錄會顯示出一連串的連接及錯誤資訊很容易被目標主電腦察覺並記錄下來,因此缺點是容易被目標系統檢測到。

$ nmap -sT 10.0.2.15

Starting Nmap 6.00 ( http://nmap.org ) at 2013-12-15 18:12 CST
Nmap scan report for 10.0.2.15
Host is up (0.00024s latency).
Not shown: 996 closed ports
PORT     STATE SERVICE
80/tcp   open  http
139/tcp  open  netbios-ssn
445/tcp  open  microsoft-ds
2222/tcp open  EtherNet/IP-1

Nmap done: 1 IP address (1 host up) scanned in 0.12 seconds

-sU : UDP掃描 (UDP Scanning)

可用來確定遠端主機開放哪些 UDP Port 原理為送出零位元組的 UDP 封包到目標主機的各連接埠,如果我們收到一個 ICMP port unreachable 無法到達的回應則可確定連接埠是關閉的,否則我們可認為該埠是打開的。

$ sudo nmap -sU 10.0.2.15

Starting Nmap 6.00 ( http://nmap.org ) at 2013-12-15 18:24 CST
Nmap scan report for 10.0.2.15
Host is up (0.0000060s latency).
Not shown: 997 closed ports
PORT    STATE         SERVICE
68/udp  open|filtered dhcpc
137/udp open          netbios-ns
138/udp open|filtered netbios-dgm

Nmap done: 1 IP address (1 host up) scanned in 1.28 seconds

-sS : TCP SYN(半公開)掃描

這種掃描技術也叫半公開式掃描 (half-open scanning),因為它沒有完成一個完整的 TCP 連接三次交握過程。此方法為向目標 Port 發送一個 SYN 封包,如果目標 Port 回應 SYN / ACK 封包則表示該 Port 處於打開狀態;若回應的是 RST / ACK 封包則表示該 Port 為關閉狀態。這種掃描方法比 TCP Connect Scan 更具隱蔽性,只有極少數的網站會對它作出記錄因此比較不會在目標系統中留下掃描痕跡。

sudo nmap -sS 10.0.2.15

Starting Nmap 6.00 ( http://nmap.org ) at 2013-12-15 18:16 CST
Nmap scan report for 10.0.2.15
Host is up (0.0000060s latency).
Not shown: 996 closed ports
PORT     STATE SERVICE
80/tcp   open  http
139/tcp  open  netbios-ssn
445/tcp  open  microsoft-ds
2222/tcp open  EtherNet/IP-1

Nmap done: 1 IP address (1 host up) scanned in 0.08 seconds

-sF -sX -sN : Stealth FIN、Xmas Tree或 NULL秘密掃描(Stealth Scanning)

一些防火墻及 Packet 過濾裝置會在重要連接 Port 守護,半公開的 SYN 封包掃描會在此時會被截獲因此要有更秘密的進行掃描;而 FIN、Xmas、NULL 掃描方法則是關閉的連接埠會對你送出的探測資訊包返回一個 RST,而打開的連接埠則對其忽略不理可參考 [RFC793],其中 FIN 掃瞄使用空的 FIN 資訊包作為探針、Xmas tree 使用 FIN、URG、PUSH 標記、Null 掃描則不用任何標記,但微軟不支援此一標準,所以 -sF,-sX,-sN 的掃瞄顯示所有連接埠都是關閉的但一個 SYN(-sS) 掃瞄卻顯示有打開連接埠,那你就能大致推斷它是 WINDOWS 平台。

$ sudo nmap -sF 10.0.2.15

Starting Nmap 6.00 ( http://nmap.org ) at 2013-12-15 18:19 CST
Nmap scan report for 10.0.2.15
Host is up (0.0000060s latency).
Not shown: 996 closed ports
PORT     STATE         SERVICE
80/tcp   open|filtered http
139/tcp  open|filtered netbios-ssn
445/tcp  open|filtered microsoft-ds
2222/tcp open|filtered EtherNet/IP-1

Nmap done: 1 IP address (1 host up) scanned in 1.27 seconds

-sF -sX -sN 三個指令的結果一樣

-sP ICMP 掃描 (Ping Sweeping)

若僅想了解網路上有哪些主電腦是開放的,你可對你指定的IP地址送出一個 ICMP 的 Echo Request 封包來偵測。但有些站台會把 ICMP 的 Echo Request 封包給關掉 (例如Microsoft.com)。在這種情況下可利用發送 TCP Ping 送一個 ACK 到目標網路上的每個主機。網路上的主機如果在線,則會返回一個 TCP RST 響應。使用帶有 Ping 掃描的 TCP Ping 選項,也就是 -PT 選項可以對網絡上指定 Port 進行掃描,它將可能通過目標邊界路由器甚至是防火牆。注意,被探測的主機上的目標 Port 無須打開,關鍵取決於是否在網路上。

$ sudo nmap -sP 10.0.2.15

Starting Nmap 6.00 ( http://nmap.org ) at 2013-12-15 18:23 CST
Nmap scan report for 10.0.2.15
Host is up.
Nmap done: 1 IP address (1 host up) scanned in 0.02 seconds

-sL : 列出子網路所有IP及對應的主機名稱

$ sudo nmap -sL 10.0.2.15

Starting Nmap 6.00 ( http://nmap.org ) at 2013-12-15 18:29 CST
Nmap scan report for 10.0.2.15
Nmap done: 1 IP address (0 hosts up) scanned in 0.03 seconds

-PS : 偵測遠端主機已開啟的通訊埠

$ sudo nmap -PS 10.0.2.15

Starting Nmap 6.00 ( http://nmap.org ) at 2013-12-15 18:34 CST
Nmap scan report for 10.0.2.15
Host is up (0.0000060s latency).
Not shown: 996 closed ports
PORT     STATE SERVICE
80/tcp   open  http
139/tcp  open  netbios-ssn
445/tcp  open  microsoft-ds
2222/tcp open  EtherNet/IP-1

Nmap done: 1 IP address (1 host up) scanned in 0.10 seconds

-sT 結果一樣

-PU : 使用UDP協定 ping 遠端的主機

$ sudo nmap -PU 10.0.2.15

Starting Nmap 6.00 ( http://nmap.org ) at 2013-12-15 18:35 CST
Nmap scan report for 10.0.2.15
Host is up (0.0000050s latency).
Not shown: 996 closed ports
PORT     STATE SERVICE
80/tcp   open  http
139/tcp  open  netbios-ssn
445/tcp  open  microsoft-ds
2222/tcp open  EtherNet/IP-1

Nmap done: 1 IP address (1 host up) scanned in 0.09 seconds

-sO : 偵測遠端主機已開啟哪些通訊協定 TCP,UDP,ICMP,…

$ sudo nmap -sO 10.0.2.15

Starting Nmap 6.00 ( http://nmap.org ) at 2013-12-15 18:36 CST
Nmap scan report for 10.0.2.15
Host is up (0.0000080s latency).
Not shown: 249 closed protocols
PROTOCOL STATE         SERVICE
1        open          icmp
2        open|filtered igmp
6        open          tcp
17       open          udp
103      open|filtered pim
136      open|filtered udplite
255      open|filtered unknown

Nmap done: 1 IP address (1 host up) scanned in 1.23 seconds

-p80 : 指定 port 掃描是否開啟, ex: 80 port

80 port 是 open 的 :

    $ sudo nmap -p80 10.0.2.15

Starting Nmap 6.00 ( http://nmap.org ) at 2013-12-15 18:33 CST
Nmap scan report for 10.0.2.15
Host is up (0.00020s latency).
PORT   STATE SERVICE
80/tcp open  http

Nmap done: 1 IP address (1 host up) scanned in 0.06 seconds

81 port 是 closed 的 :

$ sudo nmap -p81 10.0.2.15

Starting Nmap 6.00 ( http://nmap.org ) at 2013-12-15 18:33 CST
Nmap scan report for 10.0.2.15
Host is up (0.000048s latency).
PORT   STATE  SERVICE
81/tcp closed hosts2-ns

掃描網段內有開啟 80 port 的 IP

$ sudo nmap -p80 10.0.2.0/24

Starting Nmap 6.00 ( http://nmap.org ) at 2013-12-15 18:38 CST
Nmap scan report for 10.0.2.2
Host is up (0.00051s latency).
PORT   STATE SERVICE
80/tcp open  http
MAC Address: 52:54:00:12:35:02 (QEMU Virtual NIC)

Nmap scan report for 10.0.2.3
Host is up (0.00074s latency).
PORT   STATE SERVICE
80/tcp open  http
MAC Address: 52:54:00:12:35:03 (QEMU Virtual NIC)

Nmap scan report for 10.0.2.4
Host is up (0.00071s latency).
PORT   STATE SERVICE
80/tcp open  http
MAC Address: 52:54:00:12:35:04 (QEMU Virtual NIC)

Nmap scan report for 10.0.2.15
Host is up (0.00027s latency).
PORT   STATE SERVICE
80/tcp open  http

Nmap done: 256 IP addresses (4 hosts up) scanned in 10.09 seconds

掃網段指定 port

nmap comes with a nice output parameter -oG (grepable output) which makes parsing more easy.

Also it is not necessary to iterate through all IP addresses you want to scan. nmap is netmask aware.

nmap -p80 192.168.0.0/24 -oG - | grep 80/open

The -oG enables the grepable output, and - specifies the file to output to (in this case stdout). The pipe symbol redirects the output of nmap (stdout) to grep, which only returns lines containing 80/open in this case.

  • -oG filespec (grepable output) .
  • This output format is covered last because it is deprecated. The XML output format is
  • far more powerful, and is nearly as convenient for experienced users. XML is a standard
  • for which dozens of excellent parsers are available, while grepable output is my own
  • simple hack. XML is extensible to support new Nmap features as they are released, while
  • I often must omit those features from grepable output for lack of a place to put them.
  • (…略…)

ref: http://stackoverflow.com/questions/3773183/how-to-determine-which-ips-in-a-given-range-have-port-80-using-nmap 不自量力 http://idobest.pixnet.net/blog/post/22040775-%5B%E8%BD%89%E8%B2%BC%5D-linux-%E7%B6%B2%E8%B7%AF%E6%AA%A2%E6%B8%AC%E5%B7%A5%E5%85%B7-nmap-%E7%9A%84%E7%94%A8%E6%B3%95

Ruby 建立自己的 Gem 套件

建立 gem 的基本結構

jex@virtualBox:/tmp$ bundle gem exgem
      create  exgem/Gemfile                    <= 描述 dependency
      create  exgem/Rakefile                   <= 發佈和打包的 rake tasks
      create  exgem/LICENSE.txt                <= 註明 License
      create  exgem/README.md                  <= 簡單說明如何使用它
      create  exgem/.gitignore                 <= 不要進 Git 的檔案在這定義
      create  exgem/exgem.gemspec             <= gem 的 spec
      create  exgem/lib/exgem.rb              <= gem 裡的 library
      create  exgem/lib/exgem/version.rb      <= 版本紀錄
Initializating git repo in /tmp/exgem

首先看一下 Gemfile

exgem/Gemfile :

source 'https://rubygems.org'

# Specify your gem's dependencies in exgem.gemspec
gemspec

最後一行要你定義相依套件在 exgem.gemspec

開啟 GemSpec

exgem/exgem.gemspec :

裡面的內容大部份都已填好了, 所以我們改一點使它有變化

spec.description   = %q{Description : This is my gem for example.}
spec.summary       = %q{Summary : This is my gem for example.}

撰寫你的 lib

exgem/lib/exgem.rb :

加上 hi 這個 method :

require "exgem/version"

module Exgem
  # Your code goes here...
  def self.hi
    puts "Hello, world!"
  end
end

寫完之後 build

gem build exgem.gemspec
WARNING:  no homepage specified
  Successfully built RubyGem
  Name: exgem
  Version: 0.0.1
  File: exgem-0.0.1.gem
  • 出現提示 WARNING: no homepage specified 可以忽略它,
  • 因為在 exgem.gemspec 裡我們沒有定義 spec.homepage, 它是一個 URI
  • 目錄底下會多出此檔 exgem-0.0.1.gem

install 這個 package

在安裝之前你都還不能 require 它, 會噴錯誤

$ irb
2.0.0-p247 :001 > require 'exgem'
LoadError: cannot load such file -- exgem
        from /Users/apple/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/site_ruby/2.0.0/rubygems/core_ext/kernel_require.rb:55:in `require'
        from /Users/apple/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/site_ruby/2.0.0/rubygems/core_ext/kernel_require.rb:55:in `require'
        from (irb):1
        from /Users/apple/.rvm/rubies/ruby-2.0.0-p247/bin/irb:13:in `<main>'

所以要先安裝(需要 sudo 權限)

$ sudo gem install exgem-0.0.1.gem
Password:
Successfully installed exgem-0.0.1
1 gem installed

就可以 require 了

$ irb
2.0.0p247 :001 > require 'exgem'
 => true
2.0.0p247 :002 > Exgem.hi
Hello, world!
 => nil
  • 像我習慣用 tmux 分頁切來切去, 如果一 TAB 執行 gem install exgem-0.0.1.gem, 另一 TAB 執行 irb 可能會造成 require exgem 失敗
  • 最好是 irb 離開再重進一次, 才抓得到新的 gem package

發佈在 RubyGems.org

[1] 更新

gem update --system

[2] 申請一組帳號

handle 是 username 的意思

[3] 發佈到 RubyGems.org

執行

$ gem push exgem-0.0.1.gem
Pushing gem to https://rubygems.org...
Successfully registered gem: exgem (0.0.1)

官網就可以看到剛剛發佈的 gem 了 gem.JPG

gem 的相關指令

刪除

$ sudo gem uninstall exgem
Successfully uninstalled exgem-0.0.1

Q & A


如果發生錯誤

ERROR:  While executing gem ... (RuntimeError)
    Can't find 'rubygems-update' in any repo. Check `gem source list`.

解決方法

sudo gem sources -a http://s3.amazonaws.com/production.s3.rubygems.org/
http://s3.amazonaws.com/production.s3.rubygems.org/ added to sources

如果發生

gem push exgem-0.0.1.gem
Pushing gem to https://rubygems.org...
Repushing of gem versions is not allowed.
Please use `gem yank` to remove bad gem releases.

修改你的 lib/exgem/version.rb, 將版本從 0.0.1 改成 0.0.2

$ gem build exgem.gemspec
WARNING:  no homepage specified
  Successfully built RubyGem
  Name: exgem
  Version: 0.0.2
  File: exgem-0.0.2.gem

會生成 exgem-0.0.2.gem, 而舊的 exgem-0.0.1.gem 不會消失


如果發佈發生此錯誤的話表示 gem 的名稱跟別人重覆了

$ sudo gem push exgem-0.0.2.gem
Password:
Pushing gem to https://rubygems.org...
You do not have permission to push to this gem.

ref : http://blog.xdite.net/posts/2012/01/04/how-to-pack-a-gem http://weblog.rubyonrails.org/2009/9/1/gem-packaging-best-practices/ http://guides.rubygems.org/make-your-own-gem/#first-gem http://net.tutsplus.com/tutorials/ruby/gem-creation-with-bundler/ http://i3zhe.github.io/blog/2012/10/29/ru-he-zhi-zuo-zi-ji-de-gem/

PHP Yahoo Oauth 及取得基本資料

申請

[1] 到Yahoo! Developer Network登入後 -> 右上角 My Projects -> Create a Project

[2] 申請好會有一組 Application ID, Consumer Key, Consumer Secret

[3] 填入 domain 後記得驗證它, 才能用於線上

登入 Oauth, 並透過 yql 取得使用者資料 (使用 Codeigniter)

Oauth

原先 Oauth 那邊打算使用官方的 SDK, 但是怎麼試都會有 ERROR, 於是參考網路的資源重刻了一個輪子

YQL

原以為做登入 Oauth 取得的 GUID 再透過 YQL Console 的結果網址就可以取得使用者資料, 而不透過 YQL 的 SDK

例如我想取得使用者資料 YQL Console 執行

select * from social.profile where guid = "{我的GUID}"

完成後頁面下面有 url : http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20social.profile%20where%20guid%20%3D%20%22{我的GUID}%22&format=json&diagnostics=true&callback=

果然事情不是憨人想得這麼簡單, 直接拿來用會得到 ERROR 頁面

{
    error: {
        lang: "en-US",
        diagnostics: null,
        description: "Authentication Error. The table social.profile requires a higher security level than is provided, you provided ANY but at least APP is expected"
    }
}

YQL Console 頁面應該是塞了 Token, 所以只好使用正統的方法來取得了

我們要使用 Yahoo! Social SDK 請將 yos-social-php 下載到 /application/third_party, 稍後的 Library 會引入它

此練習只是取得使用者資料為例子, 取得 YQL 其它資料應該也是差不多

Oauth Library :

<?php defined('BASEPATH') OR exit('No direct script access allowed');

class Oauth {

    const CONSUMER_KEY    = "(填你自己的)";
    const CONSUMER_SECRET = "(填你自己的)";
    const APP_ID          = "(填你自己的)";
    const CALLBACK_URL    = "http://{你的 domain}/{你的 controller}/get_access_token";
    private $TOKEN;

    public function curl_post($url, $post = NULL, $options = array()) {
        $defaults = array(
            CURLOPT_POST           => 1,
            CURLOPT_HEADER         => 0,
            CURLOPT_URL            => $url,
            CURLOPT_FRESH_CONNECT  => 1,
            CURLOPT_RETURNTRANSFER => 1,
            CURLOPT_FORBID_REUSE   => 1,
            CURLOPT_TIMEOUT        => 4,
            CURLOPT_POSTFIELDS     => http_build_query($post),
        );

        $ch = curl_init();
        curl_setopt_array($ch, $defaults);
        if( ! $result = curl_exec($ch))
        {
            trigger_error(curl_error($ch));
        }
        curl_close($ch);
        return $result;
    }

    public function get_request_token()
    {
        $post = array(
            "oauth_nonce"            => md5(uniqid(rand(), true)),
            "oauth_timestamp"        => time(),
            "oauth_consumer_key"     => OAUTH::CONSUMER_KEY,
            "oauth_signature_method" => "PLAINTEXT",
            "oauth_signature"        => OAUTH::CONSUMER_SECRET."&",
            "oauth_version"          => "1.0",
            "oauth_callback"         => OAUTH::CALLBACK_URL,
        );

        $r = $this->curl_post("https://api.login.yahoo.com/oauth/v2/get_request_token", $post);
        parse_str($r, $output);
        return $output;
    }

    public function get_access_token($data)
    {
        if ( ! isset($data) || ! is_array($data))
        {
            return FALSE;
        }
        $post = array(
            "oauth_nonce"            => md5(uniqid(rand(), true)),
            "oauth_timestamp"        => time(),
            "oauth_consumer_key"     => OAUTH::CONSUMER_KEY,
            "oauth_signature_method" => "PLAINTEXT",
            "oauth_version"          => "1.0",
            "oauth_signature"        => OAUTH::CONSUMER_SECRET."&". $data["oauth_token_secret"],
            "oauth_token"            => $data['oauth_token'],
            "oauth_verifier"         => $data['oauth_verifier'],
        );

        $r = $this->curl_post("https://api.login.yahoo.com/oauth/v2/get_token", $post);
        parse_str($r, $output);
        return $output;
    }

    public function refresh_access_token($data)
    {
        if ( ! isset($data) || ! is_array($data))
        {
            return FALSE;
        }
        $cookie = get_object_vars(http_parse_cookie(getenv("HTTP_COOKIE")));
        $_COOKIE = $cookie["cookies"];
        $post = array(
            "oauth_nonce"            => md5(uniqid(rand(), true)),
            "oauth_timestamp"        => time(),
            "oauth_consumer_key"     => OAUTH::CONSUMER_KEY,
            "oauth_signature_method" => "PLAINTEXT",
            "oauth_version"          => "1.0",
            "oauth_signature"        => OAUTH::CONSUMER_SECRET."&".$data["oauth_token_secret"],
            "oauth_token"            => $data["oauth_token"],
            "oauth_session_handle"   => $data["oauth_session_handle"],
        );

        $r = $this->curl_post("https://api.login.yahoo.com/oauth/v2/get_token", $post);
        parse_str($r, $output);
        return $output;
    }

    /*
     * api : [yos-social-php github](https://github.com/yahoo/yos-social-php)
     */
    public function get_user_profile($guid = "")
    {
        if (empty($guid))
        {
            return FALSE;
        }
        require_once (APPPATH.'third_party/yos-social-php/lib/Yahoo.inc');
        $session = YahooSession::requireSession(OAUTH::CONSUMER_KEY, OAUTH::CONSUMER_SECRET, OAUTH::APP_ID);
        $user = $session->getSessionedUser();
        return $session->query("select * from social.profile where guid ='{$guid}'");
    }
}

Controller :

public function __construct()
{
    parent::__construct();
    header("Content-type: text/html; charset=utf-8");
    $this->load->library('Oauth');
    error_reporting(E_ALL ^ E_STRICT);    // ignore php notice
}

public function get_request_token()
{
    $output = $this->oauth->get_request_token();
    if ($output)
    {
        setcookie('oauth_token_secret', $output['oauth_token_secret']);
        header('Location: '. $output['xoauth_request_auth_url']);
        exit;
    }
    $this->_output_JSON(FALSE);
}

public function get_access_token()
{
    $data['oauth_token_secret'] = $_COOKIE['oauth_token_secret'];
    $data['oauth_token'] = $this->input->get_post('oauth_token');
    $data['oauth_verifier'] = $this->input->get_post('oauth_verifier');
    $output = $this->oauth->get_access_token($data);
    if ($output)
    {
        $this->get_user_profile($output['xoauth_yahoo_guid']);
    }
    $this->_output_JSON(FALSE);
}

public function get_user_profile($guid)
{
    $result = $this->oauth->get_user_profile($guid);
    $this->_output_JSON($result);
    exit;
}

private function _output_JSON_raw($result)
{
    echo json_encode(
        array(
            'status'    => (($result) ? 'ok' : 'fail'),
            'data'      => (($result) ? $result : ''),
        ),
        JSON_UNESCAPED_UNICODE
    );
}

瀏覽器執行 http://{你的 domain}/{你的 controller}/get_request_token, 輸出結果如下 :

yahoo-oauth.jpg

ref : http://code.gunblues.com/2011/02/yahoo-api-oauth.html

Du, Df 指令

du

目錄下每一個檔案/資料夾的所佔空間

du -smh *

計算資料夾容量(total)

cd /test
du -s
441800  .

-s, –summarize : display only a total for each argument

資料夾下每個資料夾的大小

cd /test
du -h

-h : 單位為 mb

列出佔用空間前 5 名

du -s /var/* | sort -rn | head -5

xargs du -s:列出資料夾大小 (單位是 K)

df

  • / : 找出你系統中的根目錄所在磁碟,並顯示相關資訊
  • -a : 全部檔案系統和各分割區的磁碟用情形
  • -h : 容量 (G / M / K)
  • -T : 列出檔案型態

只列出sd磁碟

ls /dev/sd*

列出所有磁碟(hd及sd)

ls /dev/[sh]d*

顯示磁碟資訊

$ df -h | grep /dev/sda1 | awk '{print $0"=>"$1" "$2" "$3}'
/dev/sda1       226G  2.1G  212G   1% /=>/dev/sda1 226G 2.1G