1、问题的缘由

实际开发系统的时候,经常需要用别的用户运行一个程序。比如,有些系统为保证系统安全,不允许使用root来运行。这里,我们总结了unix系统下如何解决这个问题的一些方法。同时,我们还讨论如何在python脚本里实现。

2、unix系统的方法

2.1、runuser

runuser允许使用替代用户和组ID来运行命令。如果选项-u没有给出,则回退到su兼容的语义和shell被执行。

  • runuser和su命令之间的区别在于runuser不要求输入密码(因为它可能仅由root用户执行),它使用不同的PAM配置。命令runuser不必与suid权限一起安装。
  • 当没有参数调用时,runuser默认以root用户身份运行交互式shell。
  • 为了向后兼容,runuser默认不更改当前目录并仅设置环境变量HOME和SHELL(加上USER和LOG- 如果目标用户不是root用户,则为NAME)。此版本的runuser使用PAM进行会话管理

用法:

runuser [options] -u <USER> COMMAND
runuser [options] [-] [USER [arg]...]

案例:

 runuser -l elastic -c "ls /var/opt/elastic"

如果当前用户不是root:

runuser: may not be used by non-root users

2.2、su

su允许使用替代用户和组ID来运行命令。

  • 当没有参数的情况下调用su时默认以root身份运行交互式shell。
  • 为了向后兼容,su默认不更改当前目录并仅设置环境变量HOME和SHELL(如果目标用户不是root的话,加上USER和LOGNAME)。
  • 建议始终使用--login选项(而不是快捷方式-),以避免混合环境导致的副作用,
  • su使用PAM进行认证,帐户和会话管理。在其他su实现中有一些配置选项,例如 必须通过PAM配置wheel组的支持。

案例:

$ su -l elastic
Password:*****

$ whoami
elastic

2.3、sudo

sudo允许允许的用户按照安全策略的规定,以超级用户或其他用户的身份执行命令。

  • sudo支持安全策略和输入/输出日志记录的插件体系结构。第三方可以开发和分发自己的策略和I / O日志插件与sudo前端无缝协作。
  • 默认安全策略是sudoers,通过/ etc / sudoers文件或通过LDAP配置。看PLUGINS部分获取更多信息。
  • 安全策略确定用户必须运行sudo的权限(如果有的话)。该政策可能要求用户使用密码或另一种认证机制验证自己身份。如果需要验证,如果用户的密码未在可配置的时间限制内输入,则sudo将退出。sudoers安全策略的默认密码提示超时为5分钟。安全策略可以支持凭证缓存,以允许用户在不需要认证的情况下再次运行sudo一段时间。 sudoers 安全策略的缓存凭证5分钟,除非在sudoers(5)中覆盖。通过使用-v选项运行sudo,用户无需更新缓存的凭据
         运行一个命令。当作为sudoedit被调用时,隐含-e选项。安全策略可能会记录成功和失败的尝试使用sudo。如果配置了I / O插件,则记录运行命令的输入和输出。

案例:

sudo -u jim -g audio vi ~jim/sound.txt

2.4、总结

命令

root到用户

用户到root

任何用户间

身份验证

系统支持

日志

解释

runuser

Y

N

N

不需要

Linux:是

Solaris:不

MacOS:是

N/A

不用身份验证,效率较高

su

Y

Y

Y

目标用户的密码

Linux:是

Solaris:是

MacOS:是

/var/log/auth.log

/var/log/secure

必须提供用户密码

sudo

Y

Y

Y

用户需要验证本人身份

Linux:是

Solaris:不

MacOS:是

/var/log/auth.log

/var/log/secure

用户必须是wheel组的成员,可以执行管理员的工作

3、python脚本的方法

在实际工作中,越来越多需要用python来自动化任务、集成不同的部件、处理数据。很多时候会碰到同样问题:如何在python脚本中调用不同用户来运行程序。

  • 定义一个函数来设置正在运行的进程的gid和uid。
  • 将此函数作为preexec_fn参数传递给subprocess.Popen

subprocess.Popen将使用fork / exec模型来使用preexec_fn。这等同于按顺序调用

  • os.fork(),
  • preexec_fn()(在子进程中),
  • os.exec()(在子进程中)

必须注意,由于os.setuid,os.setgid和preexec_fn仅在Unix上受支持,因此此解决方案仅支持unix及相关系统。

import os, pwd, subprocess, sys

# set gid and uid
def demote(user_uid, user_gid):
def result():
os.setgid(user_gid)
os.setuid(user_uid)
return result # run a command under a new user
def run_command(cmd, user_name, cwd):
pw_record = pwd.getpwnam(user_name)
user_name = pw_record.pw_name
user_uid = pw_record.pw_uid
user_gid = pw_record.pw_gid # get env variable
env = os.environ.copy()
env[ 'HOME' ] = pw_record.pw_dir
env[ 'LOGNAME' ] = user_name
env[ 'PWD' ] = cwd
env[ 'USER' ] = user_name
proc = subprocess.Popen(cmd,
preexec_fn=demote(user_uid, user_gid),
cwd=cwd, env=env )
return proc.communicate()

如何在unix系统中用别的用户运行一个程序?的更多相关文章

  1. 如何让Windows程序只运行一个程序实例?

    要实现VC++或者MFC只运行一个程序实例,一般采用互斥量来实现,即首先用互斥量封装一个只运行一个程序实例的函数接口: HANDLE hMutex = NULL; void MainDlg::RunS ...

  2. linux下在root用户登陆状态下,以指定用户运行脚本程序实现方式

    aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMcAAABKCAIAAACASdeXAAAEoUlEQVR4nO2dy7WlIBBFTYIoSIIkmD ...

  3. 如何在linux下安装jdk并运行java程序

    一.进入root 大家可以看到我这里用的是CentOS 6.5 系统 二.测试网络与YUM是否可用 1.测试网络 ping www.baidu.com,如下图就是通了 参考: 一.JDK安装1.lin ...

  4. Unix系统编程()进程和程序

    进程(process)是一个可执行程序(program)的实例. 程序是包含了一系列信息的文件,这些信息描述了如何在运行时创建一个进程,所包括的内容如下所示. 二进制格式标识:每个程序文件都包含用于描 ...

  5. C#:只运行一个程序

    一.通过系统事件 1.实现如下: using System; using System.Collections.Generic; using System.Linq; using System.Tex ...

  6. VC只运行一个程序实例

    方法有很多,以下只是提供一种用的多的 一. 单文档程序 在程序App类的InitInstance中添加如下代码 BOOL CDDZApp::InitInstance() { /*只运行一个实例*/ / ...

  7. Winform程序只允许运行一个程序实例

    /// <summary> /// 应用程序的主入口点. /// </summary> [STAThread] static void Main() { Application ...

  8. 在VMware装了linux系统,如何在windows系统中用xshell连接

    网上有好几种方法,不过我觉得这种比较简单 1.找到VMware菜单  打开 编辑>虚拟网络编辑器 如图: 点下面的更改设置 点确定就可以了,什么都不用改.然后回到linux系统中ifconfig ...

  9. Root用户让其他用户运行某程序

    这里以启动tomcat为例 1.安装tomcat不介绍了,自己百度 2.测试能否使用,略 3.创建tomcat用户 useradd tomcat -s /sbin/nologin 创建tomcat,禁 ...

随机推荐

  1. Jinja2 简明使用手册

    @Jinja2 简明使用手册(转载) 介绍 Jinja是基于python的模板引擎,功能比较类似于于PHP的smarty,J2ee的Freemarker和velocity. 运行需求 Jinja2需要 ...

  2. python第十四课--排序及自定义函数之自定义函数(案例四)

    整理:4中最常见的自定义函数模型1).无参无返回值2).无参有返回值3).有参无返回值4).有参有返回值 #定义无参无返回值自定义函数 def func1(): print('hello method ...

  3. OSSpinLockLock加锁机制,保证线程安全并且性能高

    在aspect_add.aspect_remove方法里面用了aspect_performLocked, 而aspect_performLocked方法用了OSSpinLockLock加锁机制,保证线 ...

  4. 【洛谷】【堆+贪心】P1484 种树

    [题目描述:] cyrcyr今天在种树,他在一条直线上挖了n个坑.这n个坑都可以种树,但为了保证每一棵树都有充足的养料,cyrcyr不会在相邻的两个坑中种树.而且由于cyrcyr的树种不够,他至多会种 ...

  5. 【openjudge】【字符串】P6374文字排版

    [描述] 给一段英文短文,单词之间以空格分隔(每个单词包括其前后紧邻的标点符号).请将短文重新排版,要求如下: 每行不超过80个字符:每个单词居于同一行上:在同一行的单词之间以一个空格分隔:行首和行尾 ...

  6. Java静态代理学习

    代理模式 代理模式的作用是:为其他对象提供一种代理以控制对这个对象的访问. 在某些情况下,一个客户不想或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用. 代理模式一般涉及 ...

  7. 权限管理系统---django版本

    权限管理:在简单的系统中,以往都是将每个权限赋予给用户,每个用户访问某个功能,通过查询db来判断用户是否有权限.但是如下情景不能够解决: 1.随着系统的复杂,权限较为复杂的时候,权限条目也多,系统角色 ...

  8. Grid Selenium

    python selenium-9 grid模式 grid是进行分布式测试的工具,由一个hub主节点和若干个node代理节点组成 1.下载Selenium Standalone Server 下载地址 ...

  9. 命令行编译执行java

    命令行编译运行java程序 使用命令 javac进行编译 和 java进行执行. javac 后面跟着的是java文件的文件名,例如 HelloWorld.java. 该命令用于将 java 源文件编 ...

  10. 矩阵求逆·学习笔记 $\times$ [$LuoguP4783$]矩阵求逆

    哦?今天在\(luogu\)上fa♂现了矩阵求逆的板子--于是就切了切. 那么我们考虑一个矩阵\(A\),它的逆矩阵记作\(A^{-1}\),其中对于矩阵这个群来讲,会有\(A \cdot A^{-1 ...