2020年4月23日 星期四

Exit status of a child process in Linux

Source https://www.geeksforgeeks.org/exit-status-child-process-linux/

It is known that fork() system call is used to create a new process which becomes child of the caller process.
Upon exit, the child leaves an exit status that should be returned to the parent. So, when the child finishes it becomes a zombie.
Whenever the child exits or stops, the parent is sent a SIGCHLD signal.
The parent can use the system call wait() or waitpid() along with the macros WIFEXITED and WEXITSTATUS with it to learn about the status of its stopped child.
(*)wait() system call : It suspends execution of the calling process until one of its children terminates.
Syntax of wait() system call:
pid_t wait(int *status);
(*)The waitpid() system call : It suspends execution of the calling process until a child specified by pid argument has changed state.
Syntax of waitpid() system call :
pid_t waitpid(pid_t pid, int *status, int options)
Note: By default, waitpid() waits only for terminated children, but this behavior is modifiable via the options argument such as WIFEXITED, WEXITSTATUS etc.
The value of pid can be :
  1. Less than -1 : Meaning wait for any child process whose process group ID is equal to the absolute value of pid.
  2. Equal to -1 : Meaning wait for any child process.
  3. Equal to 0 : Meaning wait for any child process whose process group ID is equal to that of the calling process.
  4. Greater than 0 : Meaning wait for the child whose process ID is equal to the value of pid.
WIFEXITED and WEXITSTATUS are two of the options which can be used to know the exit status of the child.
WIFEXITED(status) : returns true if the child terminated normally.
WEXITSTATUS(status) : returns the exit status of the child. This macro should be employed only if WIFEXITED returned true.
Below is a C implementation in which child uses execl() function but the path specified to execl() is undefned.
Let us see what is the exit status value of the child that parent gets.
filter_none
brightness_4
// C code to find the exit status of child process
#include
#include
#include
#include
#include
  
// Driver code
int main(void)
{
    pid_t pid = fork();
      
    if ( pid == 0 )
    {
       /* The pathname of the file passed to execl()
          is not defined   */
       execl("/bin/sh", "bin/sh", "-c", "./nopath", "NULL");
    }
  
    int status;
      
    waitpid(pid, &status, 0);
  
    if ( WIFEXITED(status) )
    {
        int exit_status = WEXITSTATUS(status);        
        printf("Exit status of the child was %d\n", 
                                     exit_status);
    }
    return 0;
}
Output:

Note : Above code may not work with online compiler as fork() is disabled.
Here the exit status is 127 which indicates that there is some problem with path or there is a typo.
Few exit status codes are listed below for extra information :
  • 1 : Miscellaneous errors, such as “divide by zero” and other impermissible operations.
  • 2 : Missing keyword or command, or permission problem.
  • 126 : Permission problem or command is not an executable
  • 128 : invalid argument to exit.
Note : The C standard does not define the meaning of return codes. Rules for the use of return codes vary on different platforms.

Linux下使用system()函數一定要謹慎

Source

曾經的曾經,被system()函數折磨過,之所以這樣,是因為對system()函數了解不夠深入。只是簡單的知道用這個函數執行一個系統命令,這遠遠不夠,它的返回值、它所執行命令的返回值以及命令執行失敗原因如何定位,這才是重點。當初因為這個函數風險較多,故拋棄不用,改用其他的方法。這裡先不說我用了什麼方法,這裡必須要搞懂system()函數,因為還是有很多人用了system()函數,有時你不得不面對它。

先來看一下system()函數的簡單介紹:
#include 
int system(const char *command);
system()通過調用/ bin / sh -c命令執行命令中指定的命令,並在命令完成後返回。在執行命令期間,SIGCHLD將被阻止,並且SIGINT和SIGQUIT將被忽略。
system()函數調用/bin/sh來執行參數指定的命令,/bin/sh 一般是一個軟連接,指向某個具體的shell,比如bash,-c選項是告訴shell從字符串command中讀取命令;
在該command執行期間,SIGCHLD是被阻塞的,好比在說:hi,內核,這會不要給我送SIGCHLD信號,等我忙完再說;
在該command執行期間,SIGINT和SIGQUIT是被忽略的,意思是進程收到這兩個信號後沒有任何動作。

再來看一下system()函數返回值:
錯誤返回的值為-1(例如fork(2)失敗),否則返回命令的返回狀態。後一個返回狀態採用wait(2)中指定的格式。因此,該命令的退出代碼將為WEXITSTATUS(status)。如果/ bin / sh無法執行,則退出狀態將是退出(127)的命令的狀態。
如果command的值為NULL,則如果shell可用,則system()返回非零,否則返回零。
為了更好的理解system()函數返回值,需要了解其執行過程,實際上system()函數執行了三步操作:
1.fork一個子進程;
2.在子進程中調用exec函數去執行command;
3.在父進程中調用wait去等待子進程結束。
對於fork失敗,system()函數返回-1。
如果exec執行成功,也即command順利執行完畢,則返回command通過exit或return返回的值。
(注意,command順利執行不代表執行成功,比如command:"rm debuglog.txt",不管文件存不存在該command都順利執行了)
如果exec執行失敗,也即command沒有順利執行,比如被信號中斷,或者command命令根本不存在,system()函數返回127.
如果command為NULL,則system()函數返回非0值,一般為1.

看一下system()函數的源碼
看完這些,我想肯定有人對system()函數返回值還是不清楚,看源碼最清楚,下面給出一個system()函數的實現:
int system(const char * cmdstring)
{
    pid_t pid;
    int status;

if(cmdstring == NULL)
{
    return (1); //如果cmdstring为空,返回非零值,一般为1
}

if((pid = fork())<0)
{
    status = -1; //fork失败,返回-1
}
else if(pid == 0)
{
    execl("/bin/sh", "sh", "-c", cmdstring, (char *)0);
    _exit(127); // exec执行失败返回127,注意exec只在失败时才返回现在的进程,成功的话现在的进程就不存在啦~~
}
else //父进程
{
    while(waitpid(pid, &status, 0) < 0)
    {
        if(errno != EINTR)
        {
            status = -1; //如果waitpid被信号中断,则返回-1
            break;
        }
    }
}

    return status; //如果waitpid成功,则返回子进程的返回状态
}
仔細看完這個system()函數的簡單實現,那麼該函數的返回值就清晰了吧,那麼什麼時候system()函數返回0呢?只在command命令返回0時。

看一下該怎麼監控system()函數執行狀態
這裡給我出的做法:
int status;
if(NULL == cmdstring) //如果cmdstring为空趁早闪退吧,尽管system()函数也能处理空指针
{
    return XXX;
}
status = system(cmdstring);
if(status < 0)
{
    printf("cmd: %s\t error: %s", cmdstring, strerror(errno)); // 这里务必要把errno信息输出或记入Log
    return XXX;
}

if(WIFEXITED(status))
{
    printf("normal termination, exit status = %d\n", WEXITSTATUS(status)); //取得cmdstring执行结果
}
else if(WIFSIGNALED(status))
{
    printf("abnormal termination,signal number =%d\n", WTERMSIG(status)); //如果cmdstring被信号中断,取得信号值
}
else if(WIFSTOPPED(status))
{
    printf("process stopped, signal number =%d\n", WSTOPSIG(status)); //如果cmdstring被信号暂停执行,取得信号值
}
到於取得子進程返回值的相關介紹可以參考另一篇文章:http://my.oschina.net/renhc/blog/35116

system()函數用起來很容易出錯,返回值太多,而且返回值很容易跟command的返回值混淆。這裡推薦使用popen()函數替代,關於popen()函數的簡單使用也可以通過上面的鏈接查看。
popen()函數較於system()函數的優勢在於使用簡單,popen()函數只返回兩個值:
成功返回子進程的status,使用WIFEXITED相關宏就可以取得command的返回結果;
失敗返回-1,我們可以使用perro()函數或strerror()函數得到有用的錯誤信息。
這篇文章只涉及了system()函數的簡單使用,還沒有談及SIGCHLD、SIGINT和SIGQUIT對system()函數的影響,事實上,之所以今天寫這篇文章,是因為項目中因有人使用了system()函數而造成了很嚴重的事故。現像是system()函數執行時會產生一個錯誤:“ No child processes ”。
關於這個錯誤的分析,感興趣的朋友可以看一下:http://my.oschina.net/renhc/blog/54582

2020年3月30日 星期一

AT command

Source https://read-and-thinking.blogspot.com/2010/03/at-command.html

標準AT command 翻譯,轉自網路…


一、 一般命令
1、 AT+CGMI 給出模塊廠商的標識。
2、 AT+CGMM 獲得模塊標識。
這個命令用來得到支持的頻帶(GSM 900,DCS 1800 或PCS 1900)。
當模塊有多頻帶時,回應可能是不同頻帶的結合。
3、 AT+CGMR 獲得改訂的軟件版本。
4、 AT+CGSN 獲得GSM模塊的IMEI(國際移動設備標識)序列號。
5、 AT+CSCS 選擇TE特徵設定。
這個命令報告TE用的是哪個狀態設定上的ME。
ME於是可以轉換每一個輸入的或顯示的字母。這個是用來發送、讀取或者撰寫短信。
6、 AT+WPCS 設定電話簿狀態。這個特殊的命令報告通過TE電話簿所用的狀態的ME。
ME於是可以轉換每一個輸入的或者顯示的字符串字母。
這個用來讀或者寫電話簿的入口。
7、 AT+CIMI 獲得IMSI。
這命令用來讀取或者識別SIM卡的IMSI(國際移動簽署者標識)。
在讀取IMSI之前應該先輸入PIN(如果需要PIN的話)。
8、 AT+CCID 獲得SIM卡的標識。這個命令使模塊讀取SIM卡上的EF-CCID文件。
9、 AT+GCAP 獲得能力表。(支持的功能)
10、 A/ 重複上次命令。只有A/命令不能重複。這命令重複前一個執行的命令。
11、 AT+CPOF 關機。這個特殊的命令停止GSM軟件堆棧和硬件層。命令AT+CFUN=0的功能與+CPOF相同。 12、 AT+CFUN 設定電話機能。這個命令選擇移動站點的機能水平。
13、 AT+CPAS 返回移動設備的活動狀態。
14、 AT+CMEE 報告移動設備的錯誤。
這個命令決定允許或不允許用結果碼「+CME ERROR:」或者「+CMS ERROR:」代替簡單的「ERROR」。
15、 AT+CKPD 小鍵盤控制。仿真ME小鍵盤執行命令。
16、 AT+CCLK 時鐘管理。這個命令用來設置或者獲得ME真實時鐘的當前日期和時間。 See : NITZ
at+cclk?

+cclk: "20/04/15,10:50:16+00"
17、 AT+CALA 警報管理。這個命令用來設定在ME中的警報日期/時間。(鬧鈴)
18、 AT+CRMP 鈴聲旋律播放。這個命令在模塊的蜂鳴器上播放一段旋律。有兩種旋律可用:到來語音、數據或傳真呼叫旋律和到來短信聲音。
19、 AT+CRSL 設定或獲得到來的電話鈴聲的聲音級別。

二、 呼叫控制命令
1、 ATD 撥號命令。這個命令用來設置通話、數據或傳真呼叫。
2、 ATH 掛機命令。
3、 ATA 接電話。
4、 AT+CEER 擴展錯誤報告。這個命令給出當上一次通話設置失敗後中斷通話的原因。
5、 AT+VTD 給用戶提供應用GSM網絡發送DTMF(雙音多頻)雙音頻。這個命令用來定義雙音頻的長度(默認值是300毫秒)。
6、 AT+VTS 給用戶提供應用GSM網絡發送DTMF雙音頻。這個命令允許傳送雙音頻。
7、 ATDL 重撥上次電話號碼。
8、 AT%Dn 數據終端就緒(DTR)時自動撥號。
9、 ATS0 自動應答。
10、 AT+CICB 來電信差。
11、 AT+CSNS 單一編號方案。
12、 AT+VGR,AT+VGT 增益控制。這個命令應用於調節喇叭的接收增益和麥克風的傳輸增益。
13、 AT+CMUT 麥克風靜音控制。
14、 AT+SPEAKER 喇叭/麥克風選擇。這個特殊命令用來選擇喇叭和麥克風。
15、 AT+ECHO 回音取消。
16、 AT+SIDET 側音修正。
17、 AT+VIP 初始化聲音參數。
18、 AT+DUI 用附加的用戶信息撥號。
19、 AT+HUI 用附加的用戶信息掛機。
20、 AT+RUI 接收附加用戶信息。

三、 網絡服務命令
1、 AT+CSQ 信號質量。
2、 AT+COPS 服務商選擇。
3、 AT+CREG 網絡註冊。獲得手機的註冊狀態。
4、 AT+WOPN 讀取***作員名字。
5、 AT+CPOL 優先***作員列表。

四、 安全命令
1、 AT+CPIN 輸入PIN。
2、 AT+CPIN2 輸入PIN2。
3、 AT+CPINC PIN的剩餘的嘗試號碼。
4、 AT+CLCK 設備鎖。
5、 AT+CPWD 改變密碼。

五、 電話簿命令
1、 AT+CPBS 選擇電話簿記憶存儲。
2、 AT+CPBR 讀取電話簿表目。
3、 AT+CPBF 查找電話簿表目。
4、 AT+CPBW 寫電話簿表目。
5、 AT+CPBP 電話簿電話查詢。
6、 AT+CPBN 電話簿移動動作。
這個特殊命令使電話簿中的條目前移或後移(按字母順序)
7、 AT+CNUM 簽署者號碼。
8、 AT+WAIP 防止在下一次重起時初始化所有的電話簿。
9、 AT+WDCP 刪除呼叫電話號碼。
10、 AT+CSVM 設置語音郵件號碼。

六、 短消息命令
1、 AT+CSMS 選擇消息服務。
支持的服務有GSM-MO、SMS-MT、SMS-CB。
2、 AT+CNMA 新信息確認應答。
3、 AT+CPMS 優先信息存儲。這個命令定義用來讀寫信息的存儲區域。
4、 AT+CMGF 優先信息格式。執行格式有TEXT方式和PDU方式。
5、 AT+CSAS 保存設置。保存+CSAS和+CSMP的參數。
6、 AT+CRES 恢復設置。
7、 AT+CSDH 顯示文本方式的參數。
8、 AT+CNMI 新信息指示。這個命令選擇如何從網絡上接收短信息。
9、 AT+CMGR 讀短信。信息從+CPMS命令設定的存儲器讀取。
10、 AT+CMGL 列出存儲的信息。
11、 AT+CMGS 發送信息。
12、 AT+CMGW 寫短信息並存儲。
13、 AT+CMSS 從存儲器中發送信息。
14、 AT+CSMP 設置文本模式的參數。
15、 AT+CMGD 刪除短信息。刪除一個或多個短信息。
16、 AT+CSCA 短信服務中心地址。
17、 AT+CSCB 選擇單元廣播信息類型。
18、 AT+WCBM 單元廣播信息標識。
19、 AT+WMSC 信息狀態(是否讀過、是否發送等等)修正。
20、 AT+WMGO 信息覆蓋寫入。
21、 AT+WUSS 不改變SMS狀態。
在執行+CMGR或+CMGL後仍保持UNREAD。

七、 追加服務命令
1、 AT+CCFC 呼叫繼續。
2、 AT+CLCK 呼叫禁止。
3、 AT+CPWD 改變追加服務密碼。
4、 AT+CCWA 呼叫等待。
5、 AT+CLIR 呼叫線確認限制。
6、 AT+CLIP 呼叫線確認陳述。
7、 AT+COLP 聯絡線確認陳述。
8、 AT+CAOC 費用報告。
9、 AT+CACM 累計呼叫計量。
10、 AT+CAMM 累計呼叫計量最大值。
11、 AT+CPUC 單價和貨幣表。
12、 AT+CHLD 呼叫相關的追加服務。
13、 AT+CLCC 列出當前的呼叫。
14、 AT+CSSN 追加服務通知。
15、 AT+CUSD 無組織的追加服務數據。
16、 AT+CCUG 關閉的用戶組。

八、 數據命令
1、 AT+CBST 信差類型選擇。
2、 AT+FCLASS 選擇模式。
這個命令把模塊設置成數據或傳真***作的特殊模式。
3、 AT+CR 服務報告控制。這個命令允許更為詳細的服務報告。
4、 AT+CRC 劃分的結果代碼。這個命令在呼叫到來時允許更為詳細的鈴聲指示。
5、 AT+ILRR 本地DTE-DCE速率報告。
6、 AT+CRLP 無線電通信線路協議參數。
7、 AT+DOPT 其他無線電通信線路參數。
8、 AT%C 數據壓縮選擇。
9、 AT+DS 是否允許V42二度數據壓縮。
10、 AT+DR 是否報告V42二度數據壓縮。
11、 AT\N 數據糾錯選擇。

九、 傳真命令
1、 AT+FTM 傳送速率。
2、 AT+FRM 接收速率
3、 AT+FTH 用HDLC協議設置傳真傳送速率。
4、 AT+FRH 用HDLC協議設置傳真接收速率。
5、 AT+FTS 停止特定時期的傳送並等待。
6、 AT+FRS 接收沉默。

十、 第二類傳真命令
1、 AT+FDT 傳送數據。
2、 AT+FDR 接收數據。
3、 AT+FET 傳送頁標點。
4、 AT+FPTS 頁轉換狀態參數。
5、 AT+FK 終止會議。
6、 AT+FBOR 頁轉換字節順序。
7、 AT+FBUF 緩衝大小報告。
8、 AT+FCQ 控制拷貝質量檢驗。
9、 AT+FCR 控制接收傳真的能力。
10、 AT+FDIS 當前會議參數。
11、 AT+FDCC 設置DCE功能參數。
12、 AT+FLID 定義本地ID串。
13、 AT+FPHCTO 頁轉換超時參數。

十一、V24-V25命令
1、 AT+IPR 確定DTE速率。
2、 AT+ICF 確定DTE-DCE特徵結構。
3、 AT+IFC 控制DTE-DCE本地流量。
4、 AT&C 設置DCD(數據攜帶檢測)信號。
5、 AT&D 設置DTR(數據終端就緒)信號。
6、 AT&S 設置DST(數據設置就緒)信號。
7、 ATO 回到聯機模式。
8、 ATQ 決定手機是否發送結果代碼。
9、 ATV 決定DCE響應格式。
10、 ATZ 恢復為缺省設置。
11、 AT&W 保存設置。
12、 AT&T 自動測試。
13、 ATE 決定是否回顯字符。
14、 AT&F 回到出廠時的設定。
15、 AT&V 顯示模塊設置情況。
16、 ATI 要求確認信息。
這命令使GSM模塊傳送一行或多行特定的信息文字。
17、 AT+WMUX 數據/命令多路復用。

十二、特殊AT命令
1、 AT+CCED 電池環境描述。
2、 AT+CCED 自動RxLev指示。
3、 AT+WIND 一般指示。
4、 AT+ALEA 在ME和MSC之間的數據密碼模式。
5、 AT+CRYPT 數據密碼模式。
6、 AT+EXPKEY 鍵管理。
7、 AT+CPLMN 在PLMN上的信息。
8、 AT+ADC 模擬數字轉換度量。
9、 AT+CMER 移動設備事件報告。
這個命令決定是否允許在鍵按下時是否主動發送結果代碼。
10、 AT+WLPR 讀取語言偏好。
11、 AT+WLPW 寫語言偏好。
12、 AT+WIOR 讀取GPIO值。
13、 AT+WIOW 寫GPIO值。
14、 AT+WIOM 輸入/輸出管理。
15、 AT+WAC 忽略命令。
這個特殊命令允許忽略SMS、SS和可用的PLMN。
16、 AT+WTONE 播放旋律。
17、 AT+WDTMF 播放DTMF旋律。
18、 AT+WDWL 下載模式。
19、 AT+WVR 配置信差的聲音速率。
20、 AT+WDR 配置數據速率。
21、 AT+WHWV 顯示硬件的版本。
22、 AT+WDOP 顯示產品的出廠日期。
23、 AT+WSVG 聲音增益選擇。
24、 AT+WSTR 返回指定狀態的狀態。
25、 AT+WSCAN 掃瞄。
26、 AT+WRIM 設置或返回鈴聲指示模式。
27、 AT+W32K 是否允許32kHz掉電方式。
28、 AT+WCDM 改變缺省旋律。
29、 AT+WSSW 顯示內部軟件版本。
30、 AT+WCCS 編輯或顯示訂製性質設置表。
31、 AT+WLCK 允許在特定的***作符上個性化ME。
32、 AT+CPHS 設置CPHS命令。
33、 AT+WBCM 電池充電管理。
34、 AT+WFM 特性管理。是否允許模塊的某些特性,如帶寬模式、SIM卡電壓等。
35、 AT+WCFM 商業特性管理。是否允許Wavecom特殊特性。
36、 AT+WMIR 允許從當前存儲的參數值創建定制的存儲鏡像。
37、 AT+WCDP 改變旋律的缺省播放器。
38、 AT+WMBN 設置SIM卡中的不同郵箱號碼。

十三、SIM卡工具箱命令
1、 AT+STSF 配置工具箱實用程序。
2、 AT+STIN 工具箱指示。
3、 AT+STGI 獲得從SIM卡發來的預期命令的信息。
4、 AT+STCR 主動提供的結果:工具箱控制反應。

2020年3月25日 星期三

Ubuntu DNS 設定

Source: https://welkinchen.pixnet.net/blog/post/5456817-ubuntu-dns-%E8%A8%AD%E5%AE%9A

有時候網路連線是好的,可以ping到外面,但是使用Domain Name無法連線,就應該是DNS Server有誤。
DNS的設定檔是 /etc/resolv.conf,但是這個檔只要重新開機(啟動網路介面)就會重新設定(被 resolvconf 自動覆蓋)。
對於透過 DHCP 自動取得 IP / DNS 的機器,並不會發生問題(只有使用 Static IP 才會)。
# DNS of Google
#nameserver  8.8.4.4
#nameserver  8.8.8.8
# DNS of HiNet
#nameserver  168.95.1.1
#nameserver  168.95.192.1
# DNS of SeedNet
#nameserver  139.175.55.244
#nameserver  139.175.150.20
# DNS of openDNS
#nameserver  208.67.220.220
#nameserver  208.67.222.222
# DNS of PRIVATE
#nameserver  10.5.254.149
#nameserver  10.5.254.150
永久修改DNS的方法
方法 1:(固定IP)
修改 /etc/network/interfaces,
加上 dns-nameservers [DNS Server IP] (最多只能有3組)
auto lo
iface lo inet loopback
auto eth0
iface eth0 inet static
address 110.5.86.78
netmask 255.255.0.0
gateway 10.5.87.254
dns-nameservers 8.8.8.8 168.95.1.1 10.5.254.150
auto eth1
iface eth1 inet dhcp
重新開機
# sudo /etc/init.d/networking restart
------------------------------
# sudo ifdown eth0
# sudo ifup eth0
方法 2:(DHCP)
使用 dhclient 鎖定網卡。
# sudo dhclient eth0
修改 /etc/dhcp3/dhclient.conf
加上
prepend domain-name-servers 8.8.8.8;
prepend domain-name-servers 168.95.1.1;
prepend domain-name-servers 10.5.254.150
重新開機
# sudo /etc/init.d/networking restart
方法 3:(DHCP)
修改 /etc/dhcp3/dhclient.conf,
加上
interface "eth0" { prepend domain-name-servers 8.8.8.8, 8.8.4.4; }
重新開機
# sudo /etc/init.d/networking restart

Identify network setting effective now.

Source: https://askubuntu.com/questions/152593/command-line-to-list-dns-servers-used-by-my-system

Ubuntu >= 15
nmcli device show  | grep IP4.DNS
Ubuntu <= 14
nmcli dev list iface  | grep IP4

2020年3月15日 星期日

出國換匯怎麼換才划算?

Source https://trekkingjourney.com/money-exchange-taiwan/
說到出國旅遊,兌換外幣是必要的行前準備,以往只能到銀行兌換外幣現鈔,隨著數位金融的興起,換外幣的方法越來越多元,也越來越便利。
在台灣換匯取得外幣現鈔,共有4種方法:
  1. 銀行臨櫃兌換
  2. 線上結匯
  3. 外幣AMT
  4. 外幣帳戶提領
這篇會介紹並比較這4種換匯方法,看完後你就知道,哪種方法匯率最優惠,還免手續費呢 !
( 繼續往下看,就知道囉… )

4種換外幣的方法

1. 銀行臨櫃兌換

銀行臨櫃兌換外幣
傳統的兌換外幣的方法,需要直接跑去銀行櫃檯兌換外幣現金。
這種方式是最耗時好力,不僅要特地跑銀行一趟,填寫申請表並排隊等待,還會被加收100元手續費,只有少數銀行(台灣銀行和兆豐銀行)免手續費。
臨櫃兌換須要配合銀行營業時間,對一般上班族來說,要請幾個小時的假,特地跑銀行一趟買外幣。
所以,這是所有兌換外幣現鈔當中,最不推薦的一種方法。

銀行換匯手續費
郵局免手續費
台灣銀行免手續費
玉山銀行每筆100元
國泰世華每筆200元
銀行臨櫃換匯手續費 (參考資料:比率網)
優點:
  • 除非在機場內,突然想加碼買外幣(擔心外幣沒帶夠),這樣在機場臨時起意想購買外幣的便利性之外,真的想不出有什麼優點可言。
PS:機場臨櫃(台灣銀行和兆豐銀行)都會加收一筆100元的手續費,相當不划算。


缺點:
  • 要配合銀行的營業時間
  • 往往花時間排隊等待換外幣
  • 很多銀行會加收一筆100元手續費

2. 線上結匯

線上結匯流程
這種方式是在線上購買外幣,通常要求2小時之內,使用轉帳方式 (實體ATM或網路銀行轉帳皆可),完成結帳。結帳後通常當天或隔天就能去銀行提領外幣現金。

線上結匯也是要跑銀行一趟去提領外幣,與銀行臨櫃的差別在於,因為外幣線上已經買好了,直接到銀行櫃台,拿交易通知書和身分證,就能快速的領到外幣,少了填表和現場排隊的時間,也無須帶大筆現鈔買外幣呢!

目前有兩家銀行提供線上結匯,如申購外幣或查看更多內容,請點選下方連結。

線上結匯最大好處是匯率優惠(減免)且免手續費,怪不得線上結匯是目前廣受大家喜愛的換匯方法。
另外,還有個額外好處,完成線上結匯付款後,並指定機場的銀行提領外幣,這麼一來,就不用特地跑銀行一趟領取外幣,出國當天在機場提領外幣就行了!
小提醒:
線上換匯,然後在機場提領外幣有個前提,因為機場銀行臨櫃並非24小時營業,還須要配合臨櫃的營業時間 (桃園國際機場臨櫃,外幣提領時間 AM 7:00 – PM 9:00)。
如果沒辦法在這段時間內抵達機場提領,還是得跑銀行分行一趟。
優點:
  • 匯率優惠減免
  • 免手續費 (他行和本行皆免手續費)
  • 可直接機場提領外幣,免特地跑銀行一趟
  • 可以選擇外幣面額大小
  • 線上24小時換匯 (2小時內要完成轉帳繳款,他行須付台幣15元跨行轉帳費)

缺點:
  • 指定提領分行地點無法更改
  • 繳款後,規定在一段時間內,完成外幣提領 (台銀10天內、兆豐14天內完成外幣提領)
  • 最快領外幣現鈔的時間在繳款後2小時才能領到
  • 還是須配合銀行的營業時間提領外幣

3. 外幣ATM

外幣ATM
近幾年興起的提領外幣方法,提領外幣很直接,方法就和領台幣現金一樣,只差在要找可以提領外幣的ATM的機台。

外幣ATM的好處更勝於線上結匯,不僅匯率優惠減免更多、免手續費、24小時皆能提領外幣,不受銀行營業時間限制。

本行或他行的用戶都能使用外幣ATM,所以不用特地去開帳戶,而且都享有免手續費,只是他行使用會收跨行提款費台幣5元,且匯率減免也比較少。


使用外幣ATM很簡單,只要用一般的金融卡即可,金額是從台幣帳戶直接扣款,唯一難處是,要去找一台可以提領外幣的ATM。
尋找外幣ATM的地點,可上各銀行官網查詢,或參考比率網資料。

機場內也有外幣ATM,出國當天直接到外幣ATM提領,這是最直接了當、簡單又乾脆的方法,不過可能存在風險,如果ATM現鈔不夠會有領不到外幣的窘境。

下方是桃園國際機場外幣ATM坐落的位置:
優點:
  • 匯率優惠減免
  • 免手續費 (他行和本行皆免手續費)
  •  直接拿一般金融卡就能提領外幣
  •  實體ATM 24小時換匯,不受限銀行營業時間限制
  •  可直接機場提領外幣,不受限機場臨櫃營業時間限制
缺點:
  • 須尋找外幣ATM的地點
  • 無法選擇外幣的面額大小 (紙鈔面額大)
  • 只提供幾種熱門外幣 (日幣、美金、人民幣)
  • 限定每次提領的金額嚴謹 (他行每次最多領等值台幣2萬)

4. 外幣帳戶提領

外幣帳戶提領現鈔流程
外幣帳戶一般拿來作定存或買賣賺匯差,通常外幣只在戶頭做買賣,不會有實體的鈔票,所以它比較特別的地方是,買賣是看即期匯率,而非現金匯率 (前三種方法皆採用現金匯率計價)。
它的優勢是…
  • 即期匯率比現金匯率,還要好。
  • 若透過網路銀行,線上買外幣又享有匯率再減免。
所以,如果同一時間買入,外幣帳戶的匯率,絕對是當中最好的。

但問題是…外幣帳戶提領現鈔,還需要收一筆匯差手續費,費用計算方式如下:
提領外幣金額 x (現金賣匯-即其賣匯)

以下方匯率表舉例來說,領1000元美金,須付台幣220元匯差手續費。
USD1000 x (31.08-30.86)= NTD 220


提領外幣帳戶看起來手續費不少,但只要買在相對低的匯率,有機會比當下買外幣來得便宜划算。
外幣匯率表
使用這種方式領取外幣,適合2種人使用:

  1. 有外匯投資經驗 這種方式須要開外幣帳戶,且要買在相對低的匯率,才能發揮它的優勢(賺匯差),所以適合有在關注匯率走動的外匯投資者。 
  1. 常使用某種外幣 例如常常會用到美金、人民幣可以考慮這種方法,利用分批買進,均分匯率波動,可以買賣外幣賺匯差又能提領現金使用,是一舉兩得的方法。
領出外幣帳戶現鈔,除了銀行臨櫃提領,也能使用外幣ATM領出,但只限定本行用戶使用。
也就是說,外幣帳戶的現鈔提領,一定要使用相同銀行的外幣ATM才行。
目前玉山和台新銀行推出優惠,使用外幣ATM提領外幣帳戶現鈔,每筆固定收匯差手續費台幣100元,以現況來看是滿優惠且便利的方案。
優點:
  • 線上24小時換匯
  • 分批買進,平均匯率波動價格
  •  當買相對低匯率,能省下匯差

缺點:
  • 若買在相對高匯率反而造成虧損,因此適合有外匯投資經驗者
  • 提領現鈔須要付一筆匯差手續費

 4種換外幣方法 – 特性比較

換匯方式1.
銀行 臨櫃
2.
線上結匯
3.
外幣ATM
4.
外幣 帳戶
匯率
依據
現金賣出匯率現金賣出匯率現金賣出匯率即期賣出匯率
匯率優惠 (減免)❌✅✅✅
手續費每次100元 /
部份銀行
免手續費
免手續費

免手續費

現金和即期
匯
率差價
24小時換匯❌✅✅✅
配合銀行時間
提領現金
✅✅❌✅
-臨櫃提領

 ❌
-外幣ATM
機場提領外幣✅✅✅✅
換外幣的4種方法 – 特性比較表

哪一種換外幣最划算?

最划算的換匯方式,主要取決於買外幣時,匯率的高低,且最好選免換匯手續費。

很明顯的,銀行臨櫃是最不划算的,匯率既沒有優惠又要加收一筆換匯手續費。
線上結匯、外幣ATM都是不錯的選擇,既免收手續費,又有匯率優惠減免,若比較這兩種方法,外幣ATM所給的匯率優惠最多。

所以在同間銀行、同個時間上,所換到現金匯率的好壞:

外幣ATM > 線上結匯 > 銀行臨櫃 

外幣帳戶提領有別於其他三種方法,採用即期匯率優於現金匯率,如果買在相對低的匯率確實是最划算的方法;相反的,如果買在相對高的匯率,領出現鈔就虧錢了,而且別忘了,外幣帳戶只要領出現鈔,都是要加收一筆匯差手續費。

所以外幣帳戶提領現金划不划算,還是要看買的匯率好不好,這方式較適用於有在關注外幣匯率走動的人。

補充說明

台灣國內 VS 國外換匯,哪個好?

像是美金、日幣、人民幣、歐元,這些比較熱門強勢的幣別,通常銀行給出的現金匯率算不錯,所以只要在台灣換好外幣現鈔即可,也會比較方便。

比較冷門或弱勢的外幣,例如越南盾、印尼幣或菲律賓披索,雖然有些銀行有賣這些外幣現鈔,但通常給出的匯率較差,而衍生出有人選擇到國外換匯的情況。
也就是在台灣兌換強勢的外幣現鈔(美金、歐元),抵達目的地後,再換取該國幣紙。

其實每次的換匯,都會損失一點匯差 (銀行賺錢手法),理論上換越多次,中間要自行吸收更多的匯差費用,反而對自己越不利。
不過以我在東南亞旅遊的經驗,像是兌換菲律賓披索或印尼盾,帶美金現鈔抵達當地後再兌換外幣,匯率換算下來還是比在台灣直接兌換好。

小提醒:國外換匯要注意,找個合法安全的私人換錢所,避免兌換到假鈔等問題。在銀行兌換會是比較安全的作法。
小結:
  • 如果要兌換美金、日幣、人民幣或歐元,這些較熱門強勢外幣,在台灣直接兌換就好。
  • 冷門弱勢的外幣(例如東南亞各國),在國外換匯通常會比台灣的匯率好。

總結

想要省錢換匯,基本上只要掌握兩點:
  1. 避免人工臨櫃服務
  1. 採用分批買進
線上換匯、外幣ATM和使用外幣帳戶其實都是不錯的方式。
其中最無腦的省錢換匯方法是使用「外幣ATM」,匯率較優惠,而且只要使用一般金融卡就能提領了,兌換外幣很直接,也是我喜歡的換匯方法。

外幣ATM近幾年看起來,機台增設越來越多,像是玉山 、兆豐、中國信託、台新和永豐銀行,這幾家提供的外幣ATM服務據點較多,出國換外幣不妨查詢一下,住家或公司附近是否有外幣ATM提款機可用。

2020年2月27日 星期四