2013年1月22日 星期二

[OSX] 製作開機隨身碟 @ Mac 10.8.2

> hdiutil convert -format UDRW -o /tmp/ubuntu ./ubuntu-12.04.1-server-amd64.iso

> diskutil unmountDisk /dev/disk1
> sudo dd if=/tmp/ubuntu.dmg of=/dev/rdisk1 bs=1m
> diskutil eject /dev/disk1

其中 /dev/disk1 和 /dev/rdisk1 都是指隨身碟裝置位置,可用 diskutil list 來查詢

2013年1月20日 星期日

Sony DSC-RX100

RX100-01


去年遊香港時,跟友人借了一台 Sony Nex-3 伴遊,雖然夜景繁榮到用智慧手機也有不錯效果,但高級一點的相機拍出來真的有不一樣的水準,因此埋下買類單眼的欲望。原先的目標和預算擺在 NEX-F3 或 NEX-5R 這類新款且可以換鏡頭的類單眼,只是左思右想後,還是選擇了 Sony RX100 這款,主要理由是旅行中不想因為鏡頭而多背一個包包,再加上買了可以換鏡頭的相機後,隱性的鏡頭預算也會慢慢在未來浮現出來 XD 最後在友人協助下,快速地敗了 Sony RX100 啦!


這次買他的時機選在年初 XXX 百貨公司周年慶,滿 1 萬送 500禮券,刷卡滿一萬送 200 禮券,接著還有 ooo 理由送 100 禮券,總之最後就拿到 1300 禮券 + 信用卡1%現金折扣。當時選在 Sony Center 下手,好處是維修方便。最近也才稍微了解網路上的 "平行輸入" 的意思,就是所謂的水貨,水貨跟公司貨的主要差別是維修問題,賣水貨的店家通常是沒有代理權的,因此維修有問題時會比較麻煩,有的甚至要消費者自行處理。有一派的認為機身可以考慮水貨、鏡頭買公司貨,不曉得理由是不是鏡頭可以用來傳家、機身壽命短?總之這次選擇公司貨,其中最大的理由是個人對相機不熟 XD 其次是水貨跟公司貨價差不到 2000 元,再加上這次除了百貨公司節慶外,Sony 自家也有打出購買送東西的優惠(一顆原廠電池+SF-16UX 記憶卡),在這樣的條件下就完全不用考慮水貨。但小提一下,最佳購入 Sony RX100 的時機是2012夏天預購活動,還會多送原廠皮套(原價2千附近)


RX100-03


故上圖主要有兩樣還是額外購買的,那就是充電器跟皮套。兩樣加起來不用 850 元 XD 就先用看看吧!


RX100-04


至於入手好的心得嘛,除了照片在自動模式隨便拍隨便好看外,另一個則是在手動模式中,透過機身右下方的轉盤,還算方便地調整快門跟光圈數值,是我覺得還滿不錯的地方。優點嘛,就真的達到輕便、又可以隨便拍隨便好看,如果有想要手動調快門、光圈和 ISO 值也能把玩,缺點嘛,除了價格外,就是預設拍出來的照片檔案大小都以 5MB 起跳,這樣拍100張就吃掉500MB的容量了 XD 未來得要勤勞整理照片了。最後補個兩張自動拍攝的夜景:


RX100 RX100


2013年1月16日 星期三

iOS 開發筆記 - 備份還原匯出 Xcode 所需鑰匙(keys)

xcode_profile_export03


昨晚把 Mac mini 重灌了,灌完才想到 Xcode 開發環境的問題,所幸現在非常方便,直接在 Xcode 操作就能很順地匯出與匯入,因此,我只需要從另一台 Mac OS X 裡,透過 Xcode 把開發要用的 public key/private key 匯出即可,早期的作法可是透過 Keychains 各別匯出。


開啟 Xcode -> Windows -> Organizer -> Team -> 下方有 Export 可選:


xcode_profile_export01


設定打包的密碼:


xcode_profile_export02


如此一來就完成匯出了,至於匯入的方式,可以參照上述 Import 或是丟到另一台電腦直接點選也行。


2013年1月14日 星期一

[C] 一行指令建立帳號、更新密碼 (需setuid) @ Ubuntu 12.04

最近有需求要幫系統加入新增帳號、修改帳密的流程,所以想著想著,就蹦出了一支 C 程式,透過 setuid 的方式,終於可以完成這項工作 (經高手指點,bash 無法被 setuid 使用,也就是設定完後無法達成想要的結果,可以在 script 裡打 id 指令)


相關 Unix 指令回顧:



  • 一行指令新增帳號


    • $ sudo adduser --quiet --gecos "" --disabled-login --no-create-home --shell "/usr/sbin/nologin" tester


  • 一行指令更新密碼


    • $ echo "tester:password" | chpasswd


  • 檢查使用者是否存在


    • $ getent passwd tester



程式碼:


#include <stdio.h>
#include <stdlib.h>
#include <string.h>


#include <sys/types.h>
#include <unistd.h>


#define CMD_ADDUSER "sudo adduser --quiet --gecos \"\" --disabled-login --no-create-home --shell \"/usr/sbin/nologin\" "
#define CMD_CHECK_USER_EXISTS "getent passwd"
#define MAX_BUFFER_LINE 1024
int main(int argc, char *argv[])
{
   char buf[MAX_BUFFER_LINE+1], pass[MAX_BUFFER_LINE+1], *cmd;
   FILE *fp;
   setuid(0); // use root
   //system("id");
   if( argc < 3 )
   {
      fprintf( stderr, "Usage> %s username [ - | password]\n\t%s username -\t\t(read password from stdin)\n\t%s username password\n\n\tothers: sudo chown root %s && sudo chmod 4755 %s\n" , argv[0], argv[0], argv[0] , argv[0], argv[0] );
      exit(1);
   }


   memset( buf, 0, MAX_BUFFER_LINE + 1);
   memset( pass, 0, MAX_BUFFER_LINE + 1);
   if( argv[2][0] != '-' )
   {
      strncpy( pass, argv[2], MAX_BUFFER_LINE );
      pass[MAX_BUFFER_LINE] = '\0';
   }
   else if( !feof( stdin ) && fgets( pass, MAX_BUFFER_LINE, stdin ) > 0 )
   {
      //printf("Pass:[%s]\n",pass);
   }


   if( strlen(pass) < 1 )
   {
      fprintf( stderr, "Error @ Init: password is empty\n" );
      exit(1);
   }

   // check account exists
   cmd = buf;
   snprintf( buf, MAX_BUFFER_LINE, "%s %s", CMD_CHECK_USER_EXISTS, argv[1] );
   fp = popen( cmd , "r" );


   memset( buf, 0, MAX_BUFFER_LINE + 1);
   fgets( buf, MAX_BUFFER_LINE, fp );
   pclose(fp);


   if( !strlen(buf) ) // create the account if not exists
   {
      // add account
      memset( buf, 0, MAX_BUFFER_LINE + 1);
      cmd = buf;
      snprintf( buf, MAX_BUFFER_LINE, "%s %s", CMD_ADDUSER, argv[1] );
      pclose( popen( cmd , "r" ) );


      // query the account
      memset( buf, 0, MAX_BUFFER_LINE + 1);
      cmd = buf;
      snprintf( buf, MAX_BUFFER_LINE, "%s %s", CMD_CHECK_USER_EXISTS, argv[1] );
      fp = popen( cmd , "r" );
      memset( buf, 0, MAX_BUFFER_LINE + 1);
      fgets( buf, MAX_BUFFER_LINE, fp );
      pclose(fp);

      if( !strstr( buf, argv[1] ) ) // user is not created
      {
         printf("Error @ create an account: user cannot be created\n");
         exit(1);
      }


      // change password
      memset( buf, 0, MAX_BUFFER_LINE + 1);
      cmd = buf;
      snprintf( buf, MAX_BUFFER_LINE, "echo \"%s:%s\" | chpasswd ", argv[1] , pass );
      fp = popen( cmd , "r" );
      memset( buf, 0, MAX_BUFFER_LINE + 1);
      fgets( buf, MAX_BUFFER_LINE, fp );
      pclose(fp);
      if( !strlen(buf) )
         printf("OK\n");
   }
   else if( strstr( buf, "/bin/false" ) || strstr( buf, "/nologin" ) ) // change password
   {
      // change password
      memset( buf, 0, MAX_BUFFER_LINE + 1);
      cmd = buf;
      snprintf( buf, MAX_BUFFER_LINE, "echo \"%s:%s\" | chpasswd ", argv[1] , pass );
      fp = popen( cmd , "r" );
      memset( buf, 0, MAX_BUFFER_LINE + 1);
      fgets( buf, MAX_BUFFER_LINE, fp );
      pclose(fp);
      if( !strlen(buf) )
         printf("OK\n");
   }
   else
   {
      printf("SKIP @ cannot change the password for '%s'.\n", argv[1]);
   }
   return 0;
}


暫時把這隻程式定位:



  • 可以新增 nologin 帳號

  • 可以修改 nologin 帳號的密碼


用法:


$ gcc main.c
$ sudo chown root ./a.out && sudo chmod 4755 ./a.out
$ ./a.out new_account new_password


若要在安全一下,可以在設定 uid 範圍,以避免改到一些系統帳號。


2013年1月11日 星期五

[PHP] 處理 PHP 5.3 php-cgi (FastCGI) 掛掉的現象 @ ARM Linux

ab_-n_3000_-c_20


最近的小任務是要在 ARM Linux 版上配置 PHP 環境,所幸同事都先編好,讓我無痛移植 XD 只是在設定過程中,雖然沒發現 php-fpm 存在(忘了編?),但至少還有隻 php-cgi 可以把玩。


既然在板子上,勢必要測試一下堪用度,所以就用 index.php ,內文用 "<?php  phpinfo(); " ,接著找另一台 Linux 跑 ab test:


terminal 1:
$ php/bin/php-cgi -b 127.0.0.1:9000


terminal 2:
$ ab -n 300 -c 20 http://10.0.0.168/index.php


這段 ab 跑下去,嗯,感覺良好,接著我再跑一次 ab 後,在 terminal 1 得 php-cgi 就跳出了(crash?),並且看到 ab report 有 Failed requests (此例是 -n 600):


Concurrency Level: 20
Time taken for tests: 1.235 seconds
Complete requests: 600
Failed requests: 100
(Connect: 0, Receive: 0, Length: 100, Exceptions: 0)
Write errors: 0
Non-2xx responses: 600
Total transferred: 160500 bytes
HTML transferred: 66200 bytes
Requests per second: 485.68 [#/sec] (mean)
Time per request: 41.180 [ms] (mean)
Time per request: 2.059 [ms] (mean, across all concurrent requests)
Transfer rate: 126.87 [Kbytes/sec] received


接著再網路打滾一陣子,看到的解法很多是 crontab 定期開後,有點失落 XD 最後當我準備編 php-fpm 前,看到對岸好文 启动 PHP 内置 FastCGI Server 的脚本 後,搞懂原理後,就迎刃而解啦!


最後使用的參數:


terminal 1:
$ export PHP_FCGI_MAX_REQUESTS=300;
$ export PHP_FCGI_CHILDREN=4;
$ /path/php/bin/php-cgi -b 127.0.0.1:9000


terminal 2:
$ ab -n 3000 -c 20 http://10.0.0.168/index.php
...
Document Path: /index.php
Document Length: 25 bytes


Concurrency Level: 20
Time taken for tests: 6.630 seconds
Complete requests: 3000
Failed requests: 0
Write errors: 0
Non-2xx responses: 3000
Total transferred: 537000 bytes
HTML transferred: 75000 bytes
Requests per second: 452.51 [#/sec] (mean)
Time per request: 44.198 [ms] (mean)
Time per request: 2.210 [ms] (mean, across all concurrent requests)
Transfer rate: 79.10 [Kbytes/sec] received


Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 1 0.3 0 4
Processing: 18 43 4.5 43 93
Waiting: 18 43 4.5 43 92
Total: 22 44 4.5 44 93
ERROR: The median and mean for the initial connection time are more than twice the standard
deviation apart. These results are NOT reliable.


Percentage of the requests served within a certain time (ms)
50% 44
66% 44
75% 45
80% 45
90% 46
95% 46
98% 59
99% 68
100% 93 (longest request)


嘖嘖,堪用堪用啊。而原先 500 個 requests 就會掛得原因是預設 PHP_FCGI_MAX_REQUESTS=500 啦,總之,如此一來,就可以繼續用 PHP 把玩了。而要重現處理完 PHP_FCGI_MAX_REQUESTS 就關掉的話,就只需設定 PHP_FCGI_CHILDREN=0 即可