Python-subprocess-执行shell命令

subprocess

控制输入和输出流
处理返回代码 -处理异常
参数、退出状态码、以及stdout和stderr

字符串格式的命令 以及  字符串序列 
  数据类型应为一个string 或则 一个sequence(list, tuple等等)
  可以是字符串,也可以是命令各个参数组成的序列。
   当该参数的值是一个字符串时,该命令的解释过程是与平台相关的,因此通常建议将args参数作为一个序列传递。
输出--输入状态嘛 输出内容 异常处理 
  subprocess.run(args, *, stdin=None, input=None, stdout=None, stderr=None, 
                 shell=False, timeout=None, check=False, universal_newlines=False)
	 如果shell为True,那么指定的命令将通过shell执行。如管道、文件名通配符、环境变量扩展功能
     shell=True时,要注意可能潜在的安全问题,需要确保所有空格和元字符都被适当地引用,以避免shell注入漏洞
 call        其功能类似于os.system(cmd)。
 check_call     执行成功则返回状态码,否则抛出异常  subprocess.CalledProcessError
 check_output() 如果执行状态码为0 则返回命令执行结果,否则抛出异常 subprocess.CalledProcessError
                 为check_output会阻塞程序,直到命令执行结束返回结果,为此还增加了一个timeout参数来防止超时
 这三个函数参数和subprocess.run()的函数参数含义相同。				 
	 check=True capture_output=True	
	    **check:**如果该参数设置为 True,并且进程退出状态码不是 0,则弹 出 CalledProcessError 异常
        capture_output: 设置为True,将捕获stdout和stderr,从而获执行命令后取返回的内容		 
 subprocess.run()、subprocess.call()、subprocess.check_call()和subprocess.check_output()
    都是通过对subprocess.Popen的封装来实现的高级函数
 
universal_newlines: 该参数影响的是输入与输出的数据格式,
  比如它的值默认为False,此时stdout和stderr的输出是字节序列;
  当该参数的值设置为True时,stdout和stderr的输出是字符串 


不需要标准输出流返回信息,则可以把输出禁用掉 
result = subprocess.run(['ping','-n','3','8.8.8.8'],shell=True,stdout=subprocess.DEVNULL)
result = subprocess.run('dir -L',shell= True,stdout=subprocess.PIPE,stderr=subprocess.PIPE,encoding='gbk')
   运行结果会被保存在返回对象的stdout属性中
subprocess.getoutput()和subprocess.getstatusoutput()函数是来自Python 2.x的commands模块的两个遗留函数。它们隐式的调用系统shell,
  并且不保证其他函数所具有的安全性和异常处理的一致性
 
subprocess模块底层的进程创建和管理是由Popen类来处理的
   Popen communicate  poll wait  terminate kill
   
类似df -Th | grep data命令的功能,实际上就是实现shell中管道的共功能
  >>  p1 = subprocess.Popen(['df', '-Th'], stdout=subprocess.PIPE)
  >>> p2 = subprocess.Popen(['grep', 'data'], stdin=p1.stdout, stdout=subprocess.PIPE)
  >>> out,err = p2.communicate()

工具类说明

 linux终端屏幕输出的同时输出到log日志文件(tee)(script)

    tee命令
    python main.py | tee log.txt
	python命令加上-u(unbuffered)参数后会强制其标准输出也同标准错误一样不通过缓存直接打印到屏幕

开发语言

 Go  
 rust 2010 Mozilla
 ruby

Rust

 cargo
 rustup 是一个命令行工具,它可以作为编译器的工具链。
  rustup 默认安装的组件:
     rustc — Rust 编译器。
     rust-std — Rust 标准库。
     cargo — 包管理和构建工具,类似于 Java 的 Maven 和 Gradle。
     rust-docs — Rust 文档。
     rustfmt — 用来格式化 Rust 源代码。
     clippy — Rust 的代码检查工具。
rustc – version,提示版本则说明安装成功
  Rust要有能力和Windows上的静态库和动态库来交互,因此Rust报错意味着缺少链接器(link.exe),
  遇到报错 error: linker `link.exe` not found

     rustup toolchain install  stable-x86_64-pc-windows-gnu
     rustup default stable-x86_64-pc-windows-gnu
  

rustc 指令只适合调式运行简单的文件,要调式大型或者项目文件请使用cargo指令
 cargo 是用于管理 projects、crates(rust 包)的命令行,并且是我们在处理 Rust 项目时最常使用的工具
  cargo --version
  
   rustup default stable-x86_64-pc-windows-gnu
   rustup toolchain install stable-x86_64-pc-windows-gnu 

Cargo更换镜像源

 rust项目的根目录(即目录下有Cargo.toml和src/文件),rust-analyzer插件可以识别到项目	   
  cargo new rustdemo ###cargo来创建一个项目:cargo new 文件名
  cargo build 打开src找到main.rs,先运行一下(cargo build),会自动生成下面的target和.gitignore;Cargo.lock;Cargo.toml等文件,他们都是项目的配置文件。包含了项目的创建名称,版本等
 
  cargo run	 

Vscode

开发环境配置(settings.json)

Linux进程

Linux下一个进程在内存里有三部分的数据,就是"代码段"、"堆栈段"和"数据段	
  Linx 中有常规方式创建进程--程序由它的进程 ID(PID)和它父进程的进程 ID(PPID)识别	
	 函数fork( )用来创建一个新的进程  返回值本身告知当前进程是子进程还是父进程
	 函数族exec( )用来启动另外的进程以取代当前运行的进程
	     Linux中,它们分别是:execl,execlp,execle,execv,execve和execvp。
		   注意:exec()是上述这些库函数的统称
   进程状态: Running  Waiting  Stopped  Zombie
   进程状态切换:
            就绪状态(ready):等待被调度
            运行状态(running)
            阻塞状态(waiting):等待资源
多个进程 	
 进程同步:控制多个进程按一定顺序执行;进程通信:进程间传输信息。 进程通信是一种手段,而进程同步是一种目的	
   进程优先级:nice   
   进程调度算法:
   同步与互斥 防止死锁
   信号量(Semaphore)
   管道
   消息队列
   共享存储
   套接字

linux执行脚本

 方法一:切换到shell脚本所在的目录(工作目录)执行shell脚本:
 方法二:以绝对路径的方式去执行bash shell脚本
 方法三:直接使用bash 或sh 来执行bash shell脚本 开启一个新子进程去执行sh脚本
 方法四: 使用source shell脚本   当前进程来进行运行

python

 subprocess 模块
    subprocess 模块首先推荐使用的是它的 run 方法,更高级的用法可以直接使用 Popen 接口
subprocess 模块提供了:
    三个常量,PIPE、STDOUT 和 DEVNULL,
	    PIPE 是管道,STDOUT 是标准输出,DEVNULL 是黑洞。
	 linux中 /dev/null是一个特殊的设备文件,这个文件接收到的任何数据都会被丢弃。因此,null这个设备通常也被成为位桶(bit bucket)或黑洞
    一个高层次的函数:run;
    一个底层次的类:Popen。
run 函数
   输入参数
       stdout=subprocess.PIPE和stderr=subprocess.PIPE以捕获标准输出和标准错误
   run 函数返回一个 CompletedProcess 对象。CompletedProcess 对象有如下属性:
       args,run 传递过来的字符串列表;
       returncode,进程的返回码;
       stdout,标准输出;
       stderr,错误输出。
	subprocess不会使用Shell来执行命令。这是出于安全考虑,以防止潜在的Shell注入攻击。
	    但有些情况下,可能需要使用Shell来执行命令,可以将shell参数设置为True   
	 if result.returncode != 0  
   run 的参数 stdin、stdout、stderr 默认是 None,此时会使用父进程的 stdin、stdout、stderr。
     可以将 stdout 参数设为 PIPE 来捕获输出	

Popen 对象,它有两个有用的方法:poll 和 wait	
	 subprocess.Popen()提供了更多的灵活性,允许与进程进行交互,而不仅仅是等待它完成
	   要将一个命令的输出传递给另一个命令
    pid poll()  communicate(input=None, timeout=None) wait(timeout=None)
    terminate() kill() send_signal(signal)

C++ 标准库

C++ 标准 I/O 函数库提供了 popen 函数,它启动另外一个进程去执行一个 shell 命令。
     这里我们称调用 popen 的进程为父进程,由 popen 启动的进程称为子进程	
     #include <stdio.h>
       FILE * popen(const char * command, const char * type);
       int pclose(FILE * stream);
 popen()函数通过创建一个管道,调用fork()产生一个子进程,执行一个shell以运行命令来开启一个进程。
   这个管道必须由pclose()函数关闭,而不是fclose()函数。pclose()函数关闭标准I/O流,等待命令执行结束,然后返回shell的终止状态。
   如果shell不能被执行,则pclose()返回的终止状态与shell已执行exit一样

Java调用Shell命令和脚本

 Runtime.getRuntime().exec()方法
     执行调用操作,JVM会启一个Process,所以我们可以通过调用Process类的以下方法,得知调用操作是否正确执行:
  Process process = Runtime.getRuntime().exec(new String[]{"/bin/sh","-c",shStr},null,null);	 
posted @ 2023-09-04 17:22  辰令  阅读(627)  评论(0)    收藏  举报