如何在unix系統中用別的用戶運行一個程序?
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系統中用別的用戶運行一個程序?