Skip to content

Latest commit

 

History

History
471 lines (311 loc) · 23.2 KB

File metadata and controls

471 lines (311 loc) · 23.2 KB

四、使日常管理活动自动化

系统管理员执行各种管理活动。这些活动可能包括文件处理、日志记录、管理 CPU 和内存、密码处理,最重要的是,备份。这些活动需要自动化。在本章中,我们将学习如何使用 Python 自动化这些活动。

在本章中,我们将介绍以下主题:

  • 通过重定向、管道和输入文件接受输入
  • 在脚本中处理运行时的密码
  • 执行外部命令并获取其输出
  • 在运行时和验证期间提示输入密码
  • 读取配置文件
  • 向脚本添加日志记录和警告代码
  • 限制 CPU 和内存的使用
  • 启动 web 浏览器
  • 使用os模块处理目录和文件
  • 正在进行备份(使用rsync

通过重定向、管道和输入文件接受输入

在本节中,我们将学习用户如何通过重定向、管道和外部输入文件接受输入。

对于通过重定向接受输入,我们使用stdinpipe是另一种重定向形式。这个概念意味着提供一个程序的输出作为另一个程序的输入。我们可以接受外部文件的输入,也可以使用 Python。

通过重定向输入

stdinstdoutos模块创建的对象。我们将编写一个脚本,其中我们将使用stdinstdout

创建一个名为redirection.py的脚本,并在其中编写以下代码:

import sys class Redirection(object):
 def __init__(self, in_obj, out_obj): self.input = in_obj self.output = out_obj def read_line(self): res = self.input.readline() self.output.write(res) return resif __name__ == '__main__':
 if not sys.stdin.isatty(): sys.stdin = Redirection(in_obj=sys.stdin, out_obj=sys.stdout) a = input('Enter a string: ') b = input('Enter another string: ') print ('Entered strings are: ', repr(a), 'and', repr(b)) 

按如下方式运行前面的程序:

$ python3 redirection.py 

我们将收到以下输出:

Output: Enter a string: hello Enter another string: python Entered strings are:  'hello' and 'python'

当程序在交互会话中运行时,stdin为键盘输入,stdout为用户终端。input()功能用于接收用户输入,print()是在终端上写入的方式(stdout

管道输入

管道是重定向的另一种形式。这种技术用于将信息从一个程序传递到另一个程序。|符号表示管道。通过使用管道技术,我们可以使用两个以上的命令,一个命令的输出作为下一个命令的输入。

现在,我们将看到如何使用管道接受输入。为此,首先我们将编写一个返回floor除法的简单脚本。创建一个名为accept_by_pipe.py的脚本,并在其中编写以下代码:

import sys for n in sys.stdin:
 print ( int(n.strip())//2 ) 

运行脚本,您将获得以下输出:

$ echo 15 | python3 accept_by_pipe.py Output: 7 

在前面的脚本中,stdin是键盘输入。我们正在对运行时输入的数字进行floor除法。楼层除法只返回商的整数部分。当我们运行程序时,我们先传递15,然后是管道|符号,然后是脚本名称。因此,我们提供15作为脚本的输入。因此执行楼层划分,我们得到的输出为7

我们可以向脚本传递多个输入。因此,在接下来的执行中,我们传递了多个输入值,如154520.,为了处理多个输入值,我们在脚本中编写了一个for循环。因此,它将首先将输入作为15,然后是45,然后20.将在每个输入的新行上打印输出,正如我们在输入值之间写入的\n。为了能够解释反斜杠,我们传递了-e标志:

$ echo -e '15\n45\n20' | python3 accept_by_pipe.py Output: 7 22 10

运行此命令后,我们在新线路上分别将154520的楼层划分为72210

按输入文件输入

在本节中,我们将学习如何从输入文件中获取输入。在 Python 中,从输入文件获取输入更容易。我们将看一个例子。但首先,我们将创建一个名为sample.txt的简单文本文件,并在其中编写以下代码:

Sample.txt

Hello World Hello Python

现在,创建一个名为accept_by_input_file.py的脚本,并在其中编写以下代码:

i = open('sample.txt','r')
o = open('sample_output.txt','w')

a = i.read()
o.write(a)

运行该程序,您将获得以下输出:

$ python3 accept_by_input_file.py $ cat sample_output.txt Hello World Hello Python

在脚本中处理运行时的密码

在本节中,我们将看一个在脚本中处理密码的简单示例。我们将创建一个名为handling_password.py的脚本,并在其中写入以下内容:

import sys import paramiko import time ip_address = "192.168.2.106" username = "student" password = "training" ssh_client = paramiko.SSHClient() ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) ssh_client.load_system_host_keys() ssh_client.connect(hostname=ip_address,\
 username=username, password=password) print ("Successful connection", ip_address) ssh_client.invoke_shell() remote_connection = ssh_client.exec_command('cd Desktop; mkdir work\n') remote_connection = ssh_client.exec_command('mkdir test_folder\n') #print( remote_connection.read() ) ssh_client.close

运行前面的脚本,您将收到以下输出:

$ python3 handling_password.py  Output: Successful connection 192.168.2.106

在前面的脚本中,我们使用了paramiko模块。paramiko模块是ssh的 Python 实现,提供客户机-服务器功能。

安装paramiko如下:

pip3 install paramiko

在前面的脚本中,我们正在远程连接到主机192.168.2.106。我们在脚本中提供了主机的用户名和密码。

运行此脚本后,您将在192.168.2.106桌面上找到一个work文件夹,test_folder可在192.168.2.106home/目录中找到。

执行外部命令并获取其输出

在本节中,我们将学习 Python 的子流程模块。使用subprocess,很容易产生新的进程并获取其返回代码、执行外部命令和启动新的应用程序。

我们将看到如何使用subprocess模块执行外部命令并在 Python 中获得它们的输出。我们将创建一个名为execute_external_commands.py的脚本,并在其中编写以下代码:

import subprocess subprocess.call(["touch", "sample.txt"]) subprocess.call(["ls"]) print("Sample file created") subprocess.call(["rm", "sample.txt"]) 
subprocess.call(["ls"]) print("Sample file deleted")

运行该程序,您将获得以下输出:

$ python3 execute_external_commands.py Output: 1.py     accept_by_pipe.py      sample_output.txt       sample.txt accept_by_input_file.py         execute_external_commands.py         output.txt        sample.py Sample.txt file created 1.py     accept_by_input_file.py         accept_by_pipe.py execute_external_commands.py  output.txt            sample_output.txt       sample.py Sample.txt file deleted

使用子流程模块捕获输出

在本节中,我们将学习如何捕获输出。我们将传递PIPE作为stdout参数以捕获输出。编写一个名为capture_output.py的脚本,并在其中编写以下代码:

import subprocess res = subprocess.run(['ls', '-1'], stdout=subprocess.PIPE,) print('returncode:', res.returncode) print(' {} bytes in stdout:\n{}'.format(len(res.stdout), res.stdout.decode('utf-8'))) 

按如下方式执行脚本:

student@ubuntu:~$ python3 capture_output.py 

执行时,我们将收到以下输出:

Output: returncode: 0 191 bytes in stdout: 1.py accept_by_input_file.py accept_by_pipe.py execute_external_commands.py getpass_example.py ouput.txt output.txt password_prompt_again.py sample_output.txt sample.py capture_output.py

在前面的脚本中,我们导入了 Python 的子流程模块,这有助于捕获输出。子流程模块用于创建新流程。它还有助于连接输入/输出管道和获取返回代码。subprocess.run()将运行作为参数传递的命令。Returncode将是您的子进程的退出状态。在输出中,如果您得到返回码为0,则表示运行成功。

在运行时和验证期间提示输入密码

在本节中,我们将学习如何在运行时处理密码。Python 中的getpass()模块会提示用户输入密码,而不会发出回声。getpass模块用于处理程序通过终端与用户交互时的密码提示。

我们将看到一些如何使用getpass模块的示例:

  1. 创建一个名为no_prompt.py的脚本,并在其中编写以下代码:
import getpass try:
 p = getpass.getpass() except Exception as error:
 print('ERROR', error) else:
 print('Password entered:', p)

在此脚本中,不会向用户提供提示。因此,默认设置为Password提示。

按如下方式运行脚本:

$ python3 no_prompt.py Output : Password: Password entered: abcd
  1. 我们将提供输入密码的提示。因此,创建一个被调用的脚本with_prompt.py,并在其中编写以下代码:
import getpass try:
 p = getpass.getpass("Enter your password: ") except Exception as error:
 print('ERROR', error) else:
 print('Password entered:', p)

现在,我们已经编写了一个脚本,它提供了输入密码的提示。按如下方式运行程序:

$ python3 with_prompt.py Output: Enter your password: Password entered: abcd

这里我们已经为用户提供了Enter your password提示。

现在,我们将编写一个脚本,如果输入错误的密码,它将只打印一条简单的消息,但不会再次提示输入正确的密码。

  1. 编写一个名为getpass_example.py的脚本,并在其中编写以下代码:
import getpass passwd = getpass.getpass(prompt='Enter your password: ') if passwd.lower() == '#pythonworld':
 print('Welcome!!') else:
 print('The password entered is incorrect!!')

按如下方式运行程序(这里我们输入了正确的密码,即#pythonworld

$ python3 getpass_example.py Output: Enter your password: Welcome!!

现在,我们将输入错误的密码并检查收到的消息:

$ python3 getpass_example.py Output: Enter your password: The password entered is incorrect!!

在这里,我们编写了一个脚本,如果我们编写了错误的密码,它将不再要求输入密码。

现在,我们将编写一个脚本,当我们提供错误的密码时,它将要求再次输入正确的密码。获取用户登录名时,使用getuser(),通过getuser()函数返回系统登录用户。创建一个名为password_prompt_again.py的脚本,并在其中编写以下代码:

import getpass user_name = getpass.getuser() print ("User Name : %s" % user_name) while True:
 passwd = getpass.getpass("Enter your Password : ") if passwd == '#pythonworld': print ("Welcome!!!") break else: print ("The password you entered is incorrect.")

运行该程序,您将获得以下输出:

student@ubuntu:~$ python3 password_prompt_again.py User Name : student Enter your Password : The password you entered is incorrect. Enter your Password : Welcome!!!

读取配置文件

在本节中,我们将学习 Python 的configparser模块。通过configparser模块,您可以为应用程序管理用户可编辑的配置文件。

这些配置文件的常见用途是,用户或系统管理员可以使用简单的文本编辑器编辑文件以设置应用程序默认值,然后应用程序将读取和解析这些文件,并根据其中写入的内容进行操作。

要读取配置文件,configparserread()方法。现在,我们将编写一个名为read_config_file.py的简单脚本。在此之前,创建一个名为read_simple.ini.ini文件,并在其中写入以下内容:read_simple.ini

[bug_tracker] url = https://timesofindia.indiatimes.com/

创建read_config_file.py并在其中输入以下内容:

from configparser import ConfigParser p = ConfigParser() p.read('read_simple.ini') print(p.get('bug_tracker', 'url'))

运行read_config_file.py将得到以下输出:

$ python3 read_config_file.py  Output: https://timesofindia.indiatimes.com/

read()方法接受多个文件名。每当扫描每个文件名时,如果该文件存在,则会打开并读取该文件。现在,我们将编写一个脚本来读取多个文件名。创建一个名为read_many_config_file.py的脚本,并在其中编写以下代码:

from configparser import ConfigParser import glob p = ConfigParser() files = ['hello.ini', 'bye.ini', 'read_simple.ini', 'welcome.ini'] files_found = p.read(files) files_missing = set(files) - set(files_found) print('Files found:  ', sorted(files_found)) print('Files missing:  ', sorted(files_missing))

运行前面的脚本,您将获得以下输出:

$ python3 read_many_config_file.py  Output Files found:   ['read_simple.ini'] Files missing:   ['bye.ini', 'hello.ini', 'welcome.ini']

在前面的示例中,我们使用了 Python 的configparser模块,它有助于管理配置文件。首先,我们创建了一个名为files的列表。read()功能将读取配置文件。在本例中,我们创建了一个名为files_found的变量,它将存储目录中存在的配置文件的名称。接下来,我们创建了另一个名为files_missing的变量,它将返回不在目录中的文件名。最后,我们正在打印存在和缺少的文件名。

向脚本添加日志记录和警告代码

在本节中,我们将了解 Python 的日志记录和警告模块。日志模块将跟踪程序中发生的事件。“警告”模块向程序员发出警告,告知语言和库中所做的更改。

现在,我们将看到一个简单的日志记录示例。我们将编写一个名为logging_example.py的脚本,并在其中编写以下代码:

import logging LOG_FILENAME = 'log.txt' logging.basicConfig(filename=LOG_FILENAME, level=logging.DEBUG,) logging.debug('This message should go to the log file') with open(LOG_FILENAME, 'rt') as f:
 prg = f.read() print('FILE:') print(prg)

按如下方式运行程序:

$ python3 logging_example.py Output: FILE: DEBUG:root:This message should go to the log file

选中hello.py,您将看到该脚本中打印的调试消息:

$ cat log.txt  Output: DEBUG:root:This message should go to the log file

现在,我们将编写一个名为logging_warnings_codes.py的脚本,并在其中编写以下代码:

import logging import warnings logging.basicConfig(level=logging.INFO,) warnings.warn('This warning is not sent to the logs') logging.captureWarnings(True) warnings.warn('This warning is sent to the logs')

按如下方式运行脚本:

$ python3 logging_warnings_codes.py Output: logging_warnings_codes.py:6: UserWarning: This warning is not sent to the logs
 warnings.warn('This warning is not sent to the logs') WARNING:py.warnings:logging_warnings_codes.py:10: UserWarning: This warning is sent to the logs
 warnings.warn('This warning is sent to the logs')

生成警告

warn()用于生成警告。现在,我们将看到一个生成警告的简单示例。编写一个名为generate_warnings.py的脚本,并在其中编写以下代码:

import warnings warnings.simplefilter('error', UserWarning) print('Before') warnings.warn('Write your warning message here') print('After')

按如下方式运行脚本:

$ python3 generate_warnings.py Output: Before: Traceback (most recent call last):
 File "generate_warnings.py", line 6, in <module> warnings.warn('Write your warning message here') UserWarning: Write your warning message here

在前面的脚本中,我们通过warn()传递了一条警告消息。我们使用了一个简单的过滤器,这样您的警告将被视为错误,程序员将相应地解决该错误。

限制 CPU 和内存的使用

在本节中,我们将了解如何限制 CPU 和内存的使用。首先,我们将编写一个脚本来限制 CPU 使用。创建一个名为put_cpu_limit.py的脚本,并在其中编写以下代码:

import resource import sys import signal import time def time_expired(n, stack):
 print('EXPIRED :', time.ctime()) raise SystemExit('(time ran out)') signal.signal(signal.SIGXCPU, time_expired) # Adjust the CPU time limit soft, hard = resource.getrlimit(resource.RLIMIT_CPU) print('Soft limit starts as  :', soft) resource.setrlimit(resource.RLIMIT_CPU, (10, hard)) soft, hard = resource.getrlimit(resource.RLIMIT_CPU) print('Soft limit changed to :', soft) print() # Consume some CPU time in a pointless exercise print('Starting:', time.ctime()) for i in range(200000):
 for i in range(200000): v = i * i # We should never make it this far print('Exiting :', time.ctime())

按如下方式运行前面的脚本:

$ python3 put_cpu_limit.py Output: Soft limit starts as  : -1 Soft limit changed to : 10 Starting: Thu Sep  6 16:13:20 2018 EXPIRED : Thu Sep  6 16:13:31 2018 (time ran out)

在前面的脚本中,我们使用了setrlimit()来限制 CPU 的使用。因此,在我们的脚本中,我们将限制设置为 10 秒。

启动网络浏览器

在本节中,我们将学习 Python 的webbrowser模块。此模块具有在浏览器应用程序中打开 URL 的功能。我们将看到一个简单的例子。创建一个名为open_web.py的脚本,并在其中编写以下代码:

import webbrowser webbrowser.open('https://timesofindia.indiatimes.com/world')

按如下方式运行脚本:

$ python3 open_web.py Output:
Url mentioned in open() will be opened in your browser.
webbrowserCommand line interface

您还可以通过命令行使用 Python 的webbrowser模块,并且可以使用所有模块。要通过命令行使用webbrowser,请运行以下命令:

$ python3 -m webbrowser -n https://www.google.com/

这里,https://www.google.com/ 将在浏览器窗口中打开。您可以使用以下两个选项:

  • -n:打开一个新窗口
  • -t:打开新页签

使用操作系统模块处理目录和文件

在本节中,我们将学习 Python 的os模块。Python 的os模块有助于实现操作系统任务。如果要执行操作系统任务,需要导入os模块。

我们将看一些与处理文件和目录相关的示例。

创建和删除目录

在本节中,我们将创建一个脚本,在该脚本中,我们将看到可以使用哪些函数来处理文件系统上的目录,包括创建、列出和删除内容。创建一个名为os_dir_example.py的脚本,并在其中编写以下代码:

import os directory_name = 'abcd' print('Creating', directory_name) os.makedirs(directory_name) file_name = os.path.join(directory_name, 'sample_example.txt') print('Creating', file_name) with open(file_name, 'wt') as f:
 f.write('sample example file') print('Cleaning up') os.unlink(file_name) os.rmdir(directory_name)       # Will delete the directory

按如下方式运行脚本:

$ python3 os_dir_example.py Output: Creating abcd Creating abcd/sample_example.txt Cleaning up

使用mkdir()创建目录时,必须已创建所有父目录。但是,当您使用makedirs()创建目录时,它将创建任何目录,该目录在不存在的路径中提到。unlink()将删除文件路径,rmdir()将删除目录路径。

检查文件系统的内容

在本节中,我们将使用listdir()列出目录的所有内容。创建一个名为list_dir.py的脚本,并在其中编写以下代码:

import os import sys print(sorted(os.listdir(sys.argv[1])))

按如下方式运行脚本:

$ python3 list_dir.py /home/student/ ['.ICEauthority', '.bash_history', '.bash_logout', '.bashrc', '.cache', '.config', '.gnupg', '.local', '.mozilla', '.pam_environment', '.profile', '.python_history', '.ssh', '.sudo_as_admin_successful', '.viminfo', '1.sh', '1.sh.x', '1.sh.x.c', 'Desktop', 'Documents', 'Downloads', 'Music', 'Pictures', 'Public', 'Templates', 'Videos', 'examples.desktop', 'execute_external_commands.py', 'log.txt', 'numbers.txt', 'python_learning', 'work']

因此,通过使用listdir(),您可以列出该文件夹的所有内容。

进行备份(使用 rsync)

这是系统管理员必须做的最重要的工作。在本节中,我们将学习如何使用rsync进行备份。rsync命令用于本地和远程复制文件和目录,并使用rsync.执行数据备份。为此,我们将编写一个名为take_backup.py的脚本,并在其中编写以下代码:

import os import shutil import time from sh import rsync def check_dir(os_dir):
 if not os.path.exists(os_dir): print (os_dir, "does not exist.") exit(1) def ask_for_confirm():
 ans = input("Do you want to Continue? yes/no\n") global con_exit if ans == 'yes': con_exit = 0 return con_exit elif ans == "no": con_exit = 1 return con_exit else:1 print ("Answer with yes or no.") ask_for_confirm() def delete_files(ending):
 for r, d, f in os.walk(backup_dir): for files in f: if files.endswith("." + ending): os.remove(os.path.join(r, files)) backup_dir = input("Enter directory to backup\n")   # Enter directory name check_dir(backup_dir) print (backup_dir, "saved.") time.sleep(3) backup_to_dir= input("Where to backup?\n") check_dir(backup_to_dir) print ("Doing the backup now!") ask_for_confirm() if con_exit == 1:
 print ("Aborting the backup process!") exit(1) rsync("-auhv", "--delete", "--exclude=lost+found", "--exclude=/sys", "--exclude=/tmp", "--exclude=/proc", "--exclude=/mnt", "--exclude=/dev", "--exclude=/backup", backup_dir, backup_to_dir)

按如下方式运行脚本:

student@ubuntu:~/work$ python3 take_backup.py Output : Enter directory to backup /home/student/work /home/student/work saved. Where to backup? /home/student/Desktop Doing the backup now! Do you want to Continue? yes/no yes

现在,检查Desktop/directory,您将在该目录中看到您的工作文件夹。rsync命令使用了几个选项,即:

  • -a:档案
  • -u:更新
  • -h:可读格式
  • -v:冗长
  • --delete:从接收方删除无关文件
  • --exclude:排除规则

总结

在本章中,我们学习了如何自动化常规管理任务。我们学习了通过各种技术接受输入、在运行时提示密码、执行外部命令、读取配置文件、在脚本中添加警告、通过脚本和命令行启动webbrowser,使用os模块处理文件和目录,以及进行备份。

在下一章中,您将了解更多关于os模块和数据处理的信息。此外,您还将了解tarfile模块以及如何使用它。

问题

  1. 如何使用readline模块?
  2. 用于读取、创建新文件、删除文件、在当前目录中列出文件的 Linux 命令有哪些?
  3. 要在 python 中运行 Linux/windows 命令,可以使用哪些软件包?
  4. 如何在配置ini文件中读取或设置新值
  5. 列出可用于查找cpu用法的库?
  6. 列出接受用户输入的不同方法?
  7. 排序和排序的区别是什么?

进一步阅读