Zsh 開發指南(第十七篇 使用 socket 文件和 TCP 實現進程間通訊)

導讀

就像我以前提到的,zsh 腳本是能夠直接使用 socket 文件(UNIX domain socket 所使用)或者 TCP 和其餘進程通訊的。若是進程都在本地,用 socket 文件效率更高些,而且不要佔用端口,權限也更好控制。若是是在不一樣機器,可使用 TCP。git

Socket 文件

UNIX domain socket 是比管道更先進的進程通訊方法,是全雙工的方式,而且穩定性更好。但性能比管道差一些,不過通常性能瓶頸都不會出如今這裏,不用考慮性能問題。並且在一個 socket 文件上能夠創建多個鏈接,更容易管理。另外若是通訊方式從 socket 文件改爲 TCP,只須要修改不多的代碼(創建和關閉鏈接的代碼稍微改一下),而從管道改爲 TCP 則要麻煩不少。github

因此建議用 zsh 寫進程交互腳本的話,直接使用 socket 文件,而不是命名管道(匿名管道就能知足需求的簡單場景忽略不計)。bash

Socket 文件的用法:微信

# 監聽鏈接端
# 首先要加載 socket 模塊
% zmodload zsh/net/socket

% zsocket -l test.sock
% listenfd=$REPLY
# 此處阻塞等待鏈接
% zsocket -a $listenfd
# 鏈接創建完成
% fd=$REPLY
% echo $fd
5

# 而後 $fd 就可讀可寫
% cat <&$fd
good複製代碼
# 發起鏈接端
# 首先要加載 socket 模塊
% zmodload zsh/net/socket

% zsocket test.sock
# 鏈接創建完成
% fd=$REPLY
% echo $fd
4

# 而後 $fd 就可讀可寫
% echo good >&$fd複製代碼

鏈接創建後,怎麼用就隨意了。實際使用時,要判斷 fd 看鏈接是否正常創建了。一般使用 socket 文件要比在網絡環境使用 TCP 穩定性高不少,通常不會鏈接中斷或者出其餘異常。另外能夠在 zsocket 後加 -v 參數,查看詳細的信息(好比使用的 fd 號)。網絡

關閉鏈接:dom

# 發起鏈接端
# fd 是以前存放 fd 號的變量,不須要加 $
% exec {fd}>&-

# 監聽鏈接端
% exec {listenfd}>&-
% exec {fd}>&-
# 刪除 socket 文件便可,若是下次再使用會從新建立,該文件不能重複使用
% rm test.sock複製代碼

TCP

使用 TCP 鏈接的方式和使用 socket 文件基本同樣。socket

# 監聽鏈接端
# 首先要加載 tcp 模塊
% zmodload zsh/net/tcp

% ztcp -l 1234
% listenfd=$REPLY
# 此處阻塞等待鏈接
% ztcp -a $listenfd
# 鏈接創建完成
% fd=$REPLY
% echo $fd
3

# 而後 $fd 就可讀可寫
% cat <&$fd
good複製代碼
# 發起鏈接端
# 首先要加載 tcp 模塊
% zmodload zsh/net/tcp

% ztcp 127.0.0.1 1234
# 鏈接創建完成
% fd=$REPLY
% echo $fd
3

# 而後 $fd 就可讀可寫
% echo good >&$fd複製代碼

關閉鏈接:tcp

# 發起鏈接端
# fd 是以前存放 fd 號的變量
% ztcp -c $fd

# 監聽鏈接端
% ztcp -c $listenfd
% ztcp -c $fd複製代碼

程序樣例

recv_tcp,監聽指定端口,並輸出發送過來的消息。使用方法:recv_tcp 端口ide

#!/bin/zsh 
zmodload zsh/net/tcp

(($+1)) || {
    echo "Usage: ${0:t} port"
    exit 1
}

ztcp -l $1
listenfd=$REPLY

[[ $listenfd == <-> ]] || exit 1

while ((1)) {
    ztcp -a $listenfd
    fd=$REPLY
    [[ $fd == <-> ]] || continue

    cat <&$fd
    ztcp -c $fd
}複製代碼

send_tcp,用來向指定機器的指定端口發一條消息。使用方法:send_tcp 機器名 端口 消息 (機器名可選,若是沒有則發到本機,消息能夠包含空格)性能

#!/bin/zsh 
zmodload zsh/net/tcp

(($# >= 2)) || {
    echo "Usage: ${0:t} [hostname] port message"
    exit 1
}

if [[ $1 == <0-65535> ]] {
    ztcp 127.0.0.1 $1
} else {
    ztcp $1 $2
    shift
}

fd=$REPLY
[[ "$fd" == <-> ]] || exit 1

echo ${*[2,-1]} >&$fd
ztcp -c $fd複製代碼

總結

本文介紹了使用 socket 文件或者 TCP 來實現兩個腳本之間通訊的方法。

全系列文章地址:github.com/goreliu/zsh…

付費解決 Windows、Linux、Shell、C、C++、AHK、Python、JavaScript、Lua 等領域相關問題,靈活訂價,歡迎諮詢,微信 ly50247。

相關文章
相關標籤/搜索