681 lines
19 KiB
Python
681 lines
19 KiB
Python
# -*- coding:utf-8 -*-
|
|
#############################################################################
|
|
# Copyright (c) 2020 Huawei Technologies Co.,Ltd.
|
|
#
|
|
# openGauss is licensed under Mulan PSL v2.
|
|
# You can use this software according to the terms
|
|
# and conditions of the Mulan PSL v2.
|
|
# You may obtain a copy of Mulan PSL v2 at:
|
|
#
|
|
# http://license.coscl.org.cn/MulanPSL2
|
|
#
|
|
# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS,
|
|
# WITHOUT WARRANTIES OF ANY KIND,
|
|
# EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
|
# MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
|
# See the Mulan PSL v2 for more details.
|
|
# ----------------------------------------------------------------------------
|
|
# Description :
|
|
#############################################################################
|
|
|
|
# ---------------command path--------------------
|
|
import os
|
|
import subprocess
|
|
import threading
|
|
import time
|
|
from subprocess import PIPE, Popen
|
|
from datetime import datetime
|
|
from datetime import timedelta
|
|
import pwd
|
|
from gspylib.common.ErrorCode import ErrorCode
|
|
from base_utils.common.exceptions import CommandNotFoundException
|
|
from base_utils.common.fast_popen import FastPopen
|
|
from base_utils.security.security_checker import SecurityChecker
|
|
|
|
CMD_PATH = ['/bin', '/usr/local/bin', '/usr/bin', '/sbin', '/usr/sbin']
|
|
CMD_CACHE = {}
|
|
BLANK_SPACE = " "
|
|
COLON = ":"
|
|
|
|
|
|
class CmdUtil(object):
|
|
""" Cmd util"""
|
|
|
|
SOURCE_CMD = 'source'
|
|
ENV_SOURCE_CMD = "source /etc/profile;source ~/.bashrc;" \
|
|
"if [ $MPPDB_ENV_SEPARATE_PATH ]; " \
|
|
"then source $MPPDB_ENV_SEPARATE_PATH; fi"
|
|
|
|
@staticmethod
|
|
def findCmdInPath(cmd, additional_paths=None, print_error=True):
|
|
"""
|
|
function: find cmd in path
|
|
input: cmd, additional_paths, printError
|
|
output: NA
|
|
"""
|
|
global CMD_CACHE
|
|
if additional_paths is None:
|
|
additional_paths = []
|
|
if cmd not in CMD_CACHE:
|
|
# Search additional paths and don't add to cache.
|
|
for p in additional_paths:
|
|
f = os.path.join(p, cmd)
|
|
if os.path.exists(f):
|
|
return f
|
|
|
|
for p in CMD_PATH:
|
|
f = os.path.join(p, cmd)
|
|
if os.path.exists(f):
|
|
CMD_CACHE[cmd] = f
|
|
return f
|
|
|
|
if cmd == "killall":
|
|
gphome = os.getenv("GPHOME")
|
|
if gphome is None or \
|
|
not os.path.exists(os.path.join(gphome, "script/killall")):
|
|
gphome = os.path.dirname(os.path.realpath(__file__)) \
|
|
+ "/../../.."
|
|
gphome = gphome.replace("\\", "\\\\").replace('"', '\\"\\"')
|
|
SecurityChecker.check_injection_char(gphome)
|
|
if gphome != "" and os.path.exists(os.path.join(gphome,
|
|
"script/killall")):
|
|
return os.path.join(gphome, "script/killall")
|
|
else:
|
|
raise Exception(ErrorCode.GAUSS_502["GAUSS_50201"] % "killall")
|
|
|
|
if print_error:
|
|
print('Command %s not found' % cmd)
|
|
search_path = CMD_PATH[:]
|
|
search_path.extend(additional_paths)
|
|
raise CommandNotFoundException(cmd, search_path)
|
|
else:
|
|
return CMD_CACHE[cmd]
|
|
|
|
@staticmethod
|
|
def getCreateFileCmd(path):
|
|
"""
|
|
function: get create file cmd
|
|
input : path
|
|
output : str
|
|
"""
|
|
return "touch '%s'" % path
|
|
|
|
@staticmethod
|
|
def getMoveFileCmd(src, dest):
|
|
"""
|
|
function: get move file cmd
|
|
input : src, dest
|
|
output : str
|
|
"""
|
|
cmd = "mv '%s' '%s'" % (src, dest)
|
|
return cmd
|
|
|
|
@staticmethod
|
|
def getRemoveCmd(path_type):
|
|
"""
|
|
function: get remove cmd
|
|
input : path_type
|
|
output : str
|
|
"""
|
|
opts = " "
|
|
if path_type == "file":
|
|
opts = " -f "
|
|
elif path_type == "directory":
|
|
opts = " -rf "
|
|
return CmdUtil.findCmdInPath('rm') + opts
|
|
|
|
@staticmethod
|
|
def getChmodCmd(permission, src, recursive=False):
|
|
"""
|
|
function: get chmod cmd
|
|
input : permission, src, recursive
|
|
output : str
|
|
"""
|
|
return CmdUtil.findCmdInPath('chmod') + \
|
|
(" -R " if recursive else BLANK_SPACE) + \
|
|
permission + BLANK_SPACE + src
|
|
|
|
@staticmethod
|
|
def getChownCmd(owner, group, src, recursive=False):
|
|
"""
|
|
function: get chown cmd
|
|
input : owner, group, src, recursive
|
|
output : str
|
|
"""
|
|
return CmdUtil.findCmdInPath('chown') + \
|
|
(" -R " if recursive else BLANK_SPACE) + owner + \
|
|
COLON + group + BLANK_SPACE + src
|
|
|
|
@staticmethod
|
|
def getCopyCmd(src, dest, path_type=""):
|
|
"""
|
|
function: get copy cmd
|
|
input : src, dest, path_type
|
|
output : str
|
|
"""
|
|
opts = " "
|
|
if path_type == "directory":
|
|
opts = " -r "
|
|
return CmdUtil.findCmdInPath('cp') + " -p -f " + opts + BLANK_SPACE + "'" + \
|
|
src + "'" + BLANK_SPACE + "'" + dest + "'"
|
|
|
|
@staticmethod
|
|
def getMoveCmd(src, dest):
|
|
"""
|
|
function: get move cmd
|
|
input : src, dest
|
|
output : str
|
|
"""
|
|
return CmdUtil.findCmdInPath('mv') + " -f " + "'" + src + \
|
|
"'" + BLANK_SPACE + "'" + dest + "'"
|
|
|
|
@staticmethod
|
|
def getMakeDirCmd(src, recursive=False):
|
|
"""
|
|
function: get make dir cmd
|
|
input : src, recursive
|
|
output : str
|
|
"""
|
|
return CmdUtil.findCmdInPath('mkdir') + \
|
|
(" -p " if recursive else BLANK_SPACE) + "'" + src + "'"
|
|
|
|
@staticmethod
|
|
def getPingCmd(host, count, interval, packet_size=56):
|
|
"""
|
|
function: get ping cmd
|
|
input : host, count, interval, packet_size
|
|
output : str
|
|
"""
|
|
opts = " "
|
|
if int(packet_size) != int(56):
|
|
opts = " -s " + str(packet_size)
|
|
return CmdUtil.findCmdInPath('ping') + BLANK_SPACE + host + " -c " + \
|
|
count + " -i " + interval + opts
|
|
|
|
@staticmethod
|
|
def getWcCmd():
|
|
"""
|
|
function: get wc cmd
|
|
input : NA
|
|
output : str
|
|
"""
|
|
return CmdUtil.findCmdInPath('wc')
|
|
|
|
@staticmethod
|
|
def getTarCmd():
|
|
"""
|
|
function: get tar cmd
|
|
input : NA
|
|
output : str
|
|
"""
|
|
return CmdUtil.findCmdInPath('tar')
|
|
|
|
@staticmethod
|
|
def getZipCmd():
|
|
"""
|
|
function: get zip cmd
|
|
input : NA
|
|
output : str
|
|
"""
|
|
return CmdUtil.findCmdInPath('zip')
|
|
|
|
@staticmethod
|
|
def getUnzipCmd():
|
|
"""
|
|
function: get unzip cmd
|
|
input : NA
|
|
output : str
|
|
"""
|
|
return CmdUtil.findCmdInPath('unzip')
|
|
|
|
@staticmethod
|
|
def getSedCmd():
|
|
"""
|
|
function: get sed cmd
|
|
input : NA
|
|
output : str
|
|
"""
|
|
return CmdUtil.findCmdInPath('sed')
|
|
|
|
@staticmethod
|
|
def getGrepCmd():
|
|
"""
|
|
function: get grep cmd
|
|
input : NA
|
|
output : str
|
|
"""
|
|
return CmdUtil.findCmdInPath('grep')
|
|
|
|
@staticmethod
|
|
def getDateCmd():
|
|
"""
|
|
function: get date cmd
|
|
input : NA
|
|
output : str
|
|
"""
|
|
return CmdUtil.findCmdInPath('date')
|
|
|
|
@staticmethod
|
|
def getAwkCmd():
|
|
"""
|
|
function: get awk cmd
|
|
input : NA
|
|
output : str
|
|
"""
|
|
return CmdUtil.findCmdInPath('awk')
|
|
|
|
@staticmethod
|
|
def getFindCmd():
|
|
"""
|
|
function: get find cmd
|
|
input : NA
|
|
output : str
|
|
"""
|
|
return CmdUtil.findCmdInPath('find')
|
|
|
|
@staticmethod
|
|
def getTouchCmd(file_name):
|
|
"""
|
|
function: get touch cmd
|
|
input : NA
|
|
output : str
|
|
"""
|
|
return CmdUtil.findCmdInPath('touch') + BLANK_SPACE + file_name
|
|
|
|
@staticmethod
|
|
def getListCmd():
|
|
"""
|
|
function: get list cmd
|
|
input : NA
|
|
output : str
|
|
"""
|
|
return CmdUtil.findCmdInPath('ls')
|
|
|
|
@staticmethod
|
|
def getSHA256Cmd():
|
|
"""
|
|
function: get sha256 cmd
|
|
input : NA
|
|
output : str
|
|
"""
|
|
return CmdUtil.findCmdInPath('sha256sum')
|
|
|
|
@staticmethod
|
|
def getCatCmd():
|
|
"""
|
|
function: get cat cmd
|
|
input : NA
|
|
output : str
|
|
"""
|
|
return CmdUtil.findCmdInPath('cat')
|
|
|
|
@staticmethod
|
|
def getCdCmd(path):
|
|
"""
|
|
function: get cd cmd
|
|
input : path
|
|
output : str
|
|
"""
|
|
return 'cd' + BLANK_SPACE + "'" + path + "'"
|
|
|
|
@staticmethod
|
|
def getAllCrontabCmd():
|
|
"""
|
|
function: get all crontab cmd
|
|
input : NA
|
|
output : str
|
|
"""
|
|
cmd = CmdUtil.findCmdInPath('crontab') + BLANK_SPACE + " -l"
|
|
return cmd
|
|
|
|
@staticmethod
|
|
def getCrontabCmd():
|
|
"""
|
|
function: get crontab cmd
|
|
input : NA
|
|
output : str
|
|
"""
|
|
return CmdUtil.findCmdInPath('crontab')
|
|
|
|
@staticmethod
|
|
def getKillProcessCmd(signal, pid):
|
|
"""
|
|
function: get kill process cmd
|
|
input : NA
|
|
output : str
|
|
"""
|
|
return CmdUtil.findCmdInPath('kill') + " -" + signal + BLANK_SPACE + pid
|
|
|
|
@staticmethod
|
|
def getKillallProcessCmd(signal, user_name, proc_name=""):
|
|
"""
|
|
function: get killall process cmd
|
|
input : signal, username, proc_name
|
|
output : str
|
|
"""
|
|
if proc_name != "":
|
|
return CmdUtil.findCmdInPath('killall') + " -s " + signal + " -u " + \
|
|
user_name + BLANK_SPACE + proc_name
|
|
return CmdUtil.findCmdInPath('killall') + " -s " + signal + " -u " + \
|
|
user_name
|
|
|
|
@staticmethod
|
|
def getXargsCmd():
|
|
"""
|
|
function: get xargs cmd
|
|
input : NA
|
|
output : str
|
|
"""
|
|
return CmdUtil.findCmdInPath('xargs')
|
|
|
|
@staticmethod
|
|
def getServiceCmd(service_name, action):
|
|
"""
|
|
function: get service cmd
|
|
input : service_name, action
|
|
output : str
|
|
"""
|
|
return CmdUtil.findCmdInPath('service') + BLANK_SPACE + service_name + \
|
|
BLANK_SPACE + action
|
|
|
|
@staticmethod
|
|
def getSystemctlCmd(service_name, action):
|
|
"""
|
|
function: get systemctl cmd
|
|
input : service_name, action
|
|
output : str
|
|
"""
|
|
return CmdUtil.findCmdInPath('systemctl') + BLANK_SPACE + action + \
|
|
BLANK_SPACE + service_name
|
|
|
|
@staticmethod
|
|
def getUlimitCmd():
|
|
"""
|
|
function: get ulimit cmd
|
|
input : NA
|
|
output : str
|
|
"""
|
|
return 'ulimit'
|
|
|
|
@staticmethod
|
|
def getGetConfValueCmd():
|
|
"""
|
|
function: get conf value cmd
|
|
input : NA
|
|
output : str
|
|
"""
|
|
return CmdUtil.findCmdInPath('getconf') + " PAGESIZE "
|
|
|
|
@staticmethod
|
|
def getMountCmd():
|
|
"""
|
|
function: get dd cmd
|
|
input : NA
|
|
output : str
|
|
"""
|
|
return CmdUtil.findCmdInPath('mount')
|
|
|
|
@staticmethod
|
|
def getEthtoolCmd():
|
|
"""
|
|
function: get eth tool cmd
|
|
input : NA
|
|
output : str
|
|
"""
|
|
return CmdUtil.findCmdInPath('ethtool')
|
|
|
|
@staticmethod
|
|
def getTailCmd():
|
|
"""
|
|
function: get tail cmd
|
|
input : NA
|
|
output : str
|
|
"""
|
|
return CmdUtil.findCmdInPath('tail')
|
|
|
|
@staticmethod
|
|
def getSshCmd(address, timeout=None):
|
|
"""
|
|
function: get ssh cmd
|
|
input : NA
|
|
output : str
|
|
"""
|
|
if timeout:
|
|
return "pssh --trace-id %s -s -t %s -H %s" % (
|
|
threading.currentThread().getName(), str(timeout), address)
|
|
return "pssh --trace-id %s -s -H %s" % (threading.currentThread().getName(), address)
|
|
|
|
@staticmethod
|
|
def getSshCommand(ip, cmd, timeout=None):
|
|
"""
|
|
function : Get ssh command
|
|
input : null
|
|
output : exe_cmd
|
|
"""
|
|
exe_cmd = "%s \"%s\"" % (CmdUtil.getSshCmd(ip, timeout=timeout), cmd)
|
|
return exe_cmd
|
|
|
|
@staticmethod
|
|
def getNtpqCmd():
|
|
"""
|
|
function: get ntpq cmd
|
|
input : NA
|
|
output : str
|
|
"""
|
|
return "/usr/sbin/ntpq -p "
|
|
|
|
@staticmethod
|
|
def getShellCmd():
|
|
"""
|
|
function: get shell cmd
|
|
input : NA
|
|
output : str
|
|
"""
|
|
return CmdUtil.findCmdInPath('sh')
|
|
|
|
@staticmethod
|
|
def getFileSHA256Cmd(fileName):
|
|
"""
|
|
function: get file sha256 cmd
|
|
input : fileName
|
|
output : str
|
|
"""
|
|
cmd = "%s '%s' | %s -F\" \" '{print $1}' " % (CmdUtil.getSHA256Cmd(),
|
|
fileName,
|
|
CmdUtil.getAwkCmd())
|
|
return cmd
|
|
|
|
@staticmethod
|
|
def getDiskFreeCmd(mounted="", inode=False):
|
|
# -P is for POSIX formatting. Prevents error
|
|
# on lines that would wrap
|
|
return CmdUtil.findCmdInPath('df') + " -Pk " + \
|
|
(" -i " if inode else " -h ") + mounted
|
|
|
|
@staticmethod
|
|
def getReplaceFileLineContentCmd(old_line, new_line, path):
|
|
"""
|
|
function: get replace file line content cmd
|
|
input : old_line, new_line, path
|
|
output : str
|
|
"""
|
|
cmd = "%s -i \"s/%s/%s/g\" '%s'" % (CmdUtil.getSedCmd(), old_line,
|
|
new_line, path)
|
|
return cmd
|
|
|
|
@staticmethod
|
|
def getDirSizeCmd(path, unit=""):
|
|
# -s only shows the total size
|
|
# unit specify the output size unit
|
|
return CmdUtil.findCmdInPath('du') + " -s " + (" -B %s " % unit
|
|
if unit else " -h ") + path
|
|
|
|
@staticmethod
|
|
def getSysConfiguration():
|
|
"""
|
|
function : The size range of PAGE_SIZE obtained by getconf
|
|
input : NA
|
|
output: string
|
|
"""
|
|
config_cmd = CmdUtil.getGetConfValueCmd()
|
|
(status, output) = subprocess.getstatusoutput(config_cmd)
|
|
# if cmd failed, then exit
|
|
if status != 0:
|
|
raise Exception(ErrorCode.GAUSS_502["GAUSS_50219"] %
|
|
"system config pagesize" +
|
|
"The cmd is %s" % config_cmd)
|
|
return output
|
|
|
|
@staticmethod
|
|
def getExecuteCmdWithUserProfile(user, user_profile, execute_cmd,
|
|
ignore_error=True):
|
|
"""
|
|
"""
|
|
if (user != "") and (os.getuid() == 0):
|
|
cmd = "su - %s -c 'source %s; %s'" % (user, user_profile, execute_cmd)
|
|
else:
|
|
cmd = "source %s; %s" % (user_profile, execute_cmd)
|
|
if ignore_error:
|
|
cmd += " 2>/dev/null"
|
|
return cmd
|
|
|
|
@staticmethod
|
|
def getUserLimits(limit_type):
|
|
"""
|
|
function : Get current user process limits
|
|
input : string
|
|
output: string
|
|
"""
|
|
limit = CmdUtil.getUlimitCmd()
|
|
limit_cmd = "%s -a | %s -F '%s'" % (limit, CmdUtil.getGrepCmd(), limit_type)
|
|
(status, output) = subprocess.getstatusoutput(limit_cmd)
|
|
# if cmd failed, then exit
|
|
if status != 0:
|
|
raise Exception(ErrorCode.GAUSS_514["GAUSS_51400"] % limit_cmd +
|
|
" Error:\n%s" % output)
|
|
return output
|
|
|
|
@staticmethod
|
|
def retryGetstatusoutput(cmd, retry_time=3, sleep_time=1, check_output=False):
|
|
"""
|
|
function : retry getStatusoutput
|
|
@param cmd: command going to be execute
|
|
@param retry_time: default retry 3 times after execution failure
|
|
@param sleep_time: default sleep 1 second then start retry
|
|
"""
|
|
retry_time += 1
|
|
for _ in range(retry_time):
|
|
(status, output) = subprocess.getstatusoutput(cmd)
|
|
if status != 0:
|
|
time.sleep(sleep_time)
|
|
elif check_output:
|
|
if str(output).strip():
|
|
break
|
|
else:
|
|
time.sleep(sleep_time)
|
|
else:
|
|
break
|
|
return status, output
|
|
|
|
@staticmethod
|
|
def retry_util_timeout(cmd, timeout, sleep_time=1):
|
|
"""
|
|
retry execute cmd with giving timeout.
|
|
"""
|
|
end_time = datetime.now() + timedelta(seconds=int(timeout))
|
|
status, output = 1, 1
|
|
while datetime.now() < end_time:
|
|
status, output = CmdUtil.getstatusoutput_by_fast_popen(cmd)
|
|
if status == 0:
|
|
break
|
|
else:
|
|
time.sleep(sleep_time)
|
|
return status, output
|
|
|
|
@staticmethod
|
|
def getstatusoutput_by_fast_popen(cmd):
|
|
"""
|
|
get status, output by executing command by fast popen
|
|
"""
|
|
fast_popen = FastPopen(cmd, stdout=PIPE, stderr=PIPE,
|
|
close_fds=True, preexec_fn=os.setsid)
|
|
stdout, stderr = fast_popen.communicate()
|
|
output = (stdout + stderr).strip()
|
|
return fast_popen.returncode, output
|
|
|
|
@staticmethod
|
|
def exec_by_popen(cmd):
|
|
"""
|
|
execute cmd by popen
|
|
"""
|
|
env_source_cmd = CmdUtil.get_env_source_cmd()
|
|
proc = Popen("%s;%s" % (env_source_cmd, cmd), shell=True, stdout=PIPE,
|
|
stderr=PIPE, universal_newlines=True)
|
|
stdout, stderr = proc.communicate()
|
|
if proc.returncode == 0:
|
|
return True, stdout
|
|
return False, stderr
|
|
|
|
@staticmethod
|
|
def get_env_source_cmd():
|
|
"""
|
|
get env source cmd
|
|
"""
|
|
env_source_cmd = CmdUtil.ENV_SOURCE_CMD
|
|
return env_source_cmd
|
|
|
|
@staticmethod
|
|
def retry_exec_by_popen(cmd, retry_time=3, sleep_time=1, check_out=False):
|
|
"""
|
|
function : retry exec_by_popen
|
|
@param cmd: command going to be execute
|
|
@param retry_time: default retry 3 times after execution failure
|
|
@param sleep_time: default sleep 1 second then start retry
|
|
"""
|
|
retry_time += 1
|
|
for _ in range(retry_time):
|
|
(status, output) = CmdUtil.exec_by_popen(cmd)
|
|
if not status:
|
|
time.sleep(sleep_time)
|
|
|
|
elif check_out:
|
|
if str(output).strip():
|
|
break
|
|
else:
|
|
time.sleep(sleep_time)
|
|
else:
|
|
break
|
|
return status, output
|
|
|
|
@staticmethod
|
|
def interactive_with_popen(cmd, password):
|
|
"""
|
|
function : Interactive password entry
|
|
input : cmd, password
|
|
output: NA
|
|
"""
|
|
env_source_cmd = CmdUtil.get_env_source_cmd()
|
|
if isinstance(password, str):
|
|
password = bytes(password, 'utf-8')
|
|
try:
|
|
proc = Popen("%s; %s" % (env_source_cmd, cmd),
|
|
shell=True,
|
|
stdout=PIPE,
|
|
stderr=PIPE,
|
|
stdin=PIPE)
|
|
|
|
proc.stdin.write(password)
|
|
proc.stdin.write(bytes("\n", 'utf-8'))
|
|
proc.stdin.flush()
|
|
except Exception:
|
|
output, error = proc.communicate()
|
|
return proc.returncode, output, error
|
|
else:
|
|
# Increase the system response time
|
|
time.sleep(0.1)
|
|
proc.stdin.write(password)
|
|
proc.stdin.write(bytes("\n", 'utf-8'))
|
|
proc.stdin.flush()
|
|
output, error = proc.communicate()
|
|
return proc.returncode, output, error
|