diff --git a/apisix/core/utils.lua b/apisix/core/utils.lua index cfea756542bd..d9da984f32c8 100644 --- a/apisix/core/utils.lua +++ b/apisix/core/utils.lua @@ -33,15 +33,16 @@ local base = require("resty.core.base") local open = io.open local sub_str = string.sub local str_byte = string.byte +local str_gsub = string.gsub local tonumber = tonumber local tostring = tostring local re_gsub = ngx.re.gsub local re_match = ngx.re.match local re_gmatch = ngx.re.gmatch local type = type -local io_popen = io.popen local C = ffi.C local ffi_string = ffi.string +local ffi_new = ffi.new local get_string_buf = base.get_string_buf local exiting = ngx.worker.exiting local ngx_sleep = ngx.sleep @@ -56,6 +57,8 @@ local max_sleep_interval = 1 ffi.cdef[[ int ngx_escape_uri(char *dst, const char *src, size_t size, int type); + int gethostname(char *name, size_t len); + char *strerror(int errnum); ]] @@ -256,19 +259,17 @@ function _M.gethostname() return hostname end - local hd = io_popen("/bin/hostname") - local data, err = hd:read("*a") - if err == nil then - hostname = data - if string.has_suffix(hostname, "\r\n") then - hostname = sub_str(hostname, 1, -3) - elseif string.has_suffix(hostname, "\n") then - hostname = sub_str(hostname, 1, -2) - end + local size = 256 + local buf = ffi_new("unsigned char[?]", size) + + local res = C.gethostname(buf, size) + if res == 0 then + local data = ffi_string(buf, size) + hostname = str_gsub(data, "%z+$", "") else hostname = "unknown" - log.error("failed to read output of \"/bin/hostname\": ", err) + log.error("failed to call gethostname(): ", ffi_string(C.strerror(ffi.errno()))) end return hostname diff --git a/t/core/utils.t b/t/core/utils.t index 9faa545e17e1..28fa537f3674 100644 --- a/t/core/utils.t +++ b/t/core/utils.t @@ -393,3 +393,43 @@ res:nil res:5 res:12 res:7 + + + +=== TEST 13: gethostname +--- config + location /t { + content_by_lua_block { + local core = require("apisix.core") + local hostname = core.utils.gethostname() + ngx.say("hostname: ", hostname) + local hostname2 = core.utils.gethostname() + ngx.say("hostname cached: ", hostname == hostname2) + ngx.say("hostname valid: ", hostname ~= "") + + local handle = io.popen("/bin/hostname") + if handle then + local system_hostname = handle:read("*a") + handle:close() + if system_hostname then + system_hostname = string.gsub(system_hostname, "\n$", "") + ngx.say("system hostname: ", system_hostname) + ngx.say("hostname match: ", hostname == system_hostname) + else + ngx.say("system hostname: failed to read") + ngx.say("hostname match: unable to verify") + end + else + ngx.say("system hostname: failed to execute /bin/hostname") + ngx.say("hostname match: unable to verify") + end + } + } +--- request +GET /t +--- response_body_like +hostname: .+ +hostname cached: true +hostname valid: true +system hostname: .+ +hostname match: true