OpenResty OpsLang™ 快速上手

目錄

常規

首先 opslang 作為一門語言,通常語言所有的特性功能也是有的,比如定義變數,邏輯運算等等,比如下面這個例子(可以先忽略 goalrun 等關鍵詞)

# t.ops
goal all {
    run {
        my Int $foo = 1;
        my Int $bar = 2;
        say("foo + bar = ", $foo + $bar);
    }
}

執行結果:

$ opsrun t.ops
foo + bar = 3

呼叫 shell 命令

然後 opslang 強大之處則是與 shell 互動,比如一般的執行 shell 命令, 同時,shell 命令裡還可以直接使用 opslang 裡面的變數

goal all {
    run {
        my Str $name = "opslang";

        $ echo -n "hello world, my name is $.name",
        say("shell out: ", cmd-out);
    }
}

執行結果:

$ opsrun t.ops
shell out: hello world, my name is opslang

流式匹配 shell 輸出內容

是的,這個看起來比較普通,一般語言也可以做到,那麼我來試下高階一些的用法。 比如:

goal all {
    run {
        my Str $name;
        my Int $age;

        $ echo "hello, my name is opslang, I'm 1 years old",
        stream {
            out contains rx/name is (\w+)/ =>
                $name = $1;

            out contains rx/(\d+) years old/ =>
                $age = $1;

            found-prompt => break;
        },
        say("name: $name, age: $age");
    }
}

執行結果:

$ opsrun t.ops
name: opslang, age: 1

與 shell 互動

嗯,這個看起來也還好,我們再來看看,比如:

goal all {
    run {
        my Str $var = "foo";

        sh/read foo/,    # shell 會等待一個輸入
        send-text($var),
        send-key("\n"),
        $ echo -n $foo,
        say("variable foo: ", cmd-out);
    }
}

執行結果:

$ opsrun t.ops
variable foo: foo

哦,看起來有點意思,不過好像沒有啥實際作用,我們繼續, 比如,修改當前使用者密碼

goal all {
    run {
        my Str $old-password = "aoleipah1";
        my Str $new-password = "To5Geefohx";

        $ passwd,
        stream {
            out contains "(current) UNIX password" =>
                send-text($old-password),
                send-key("\n");

            out contains "New password:" =>
                send-text($new-password),
                send-key("\n");

            out contains "Retype new password:" =>
                send-text($new-password),
                send-key("\n");

            out contains "updated successfully." =>
                say("updated successfully.");

            found-prompt => break;
        };
    }
}

執行結果:

$ opsrun t.ops
updated successfully.

遠端執行

看到這裡,我想你應該對 opslang 有一些感覺了,是的,opslang 完全可以做到像人類操作終端一樣,我們繼續更高階的玩法。 比如:

goal all {
    run {
        my Str $remote-server-ip = "1.2.3.4";
        my Str $local-hostname = hostname;
        my Str $remote-hostname;

        sh/ssh -o StrictHostKeyChecking=no -o "ConnectTimeout=20" root@$.remote-server-ip/,
        setup-sh,

        $ echo "hello, I'm opslang, I come from $.local-hostname" > i-am-here.log,
        $remote-hostname = hostname,

        exit-sh,

        say("I'm back from $remote-hostname, I'm in ", hostname, " now.")
    }
}

執行結果:

$ opsrun t.ops
I'm back from remote, I'm in localhost now.

同時,我們也可以在遠端機器上看到 /root/i-am-here.log 的檔案內容為:

hello, I'm opslang, I come from localhost

是不是有點像孫猴子在五指山上寫的到此一遊呢,嗯,對的,有了 opslang 確實有這種魔力,我們也可以變很多戲法了。

opslang 非常適合用來自動化很多繁瑣的任務,讓我們從繁瑣的任務中解放出來,更多的享受程式設計的樂趣。

更多有趣的功能,比如模擬多終端,非同步執行等,以及更詳細的語法介紹,請檢視 OpenResty OpsLang™ 使用者手冊

除錯

哦,還有一個彩蛋,如果執行時有非預期的情況出現,需要除錯怎麼辦呢?不用擔心,opslang 會自動實時記錄完整的 shell 互動歷史,包括輸入和輸出。

如果是本地執行,預設會在當前目錄有一個 ops.script.log 檔案,直接 cat ops.script.log 即可看到非常友好的輸出,甚至還有語法高亮,可以隨時檢視,再也不用擔心輸出太多被刷屏了。