2011-11-23 155 views
17

我們的IT環境中有許多Red Hat Linux服務器。我的團隊成員要求我寫一個腳本(最好是shell腳本),以便使用SSH在單步執行中更改每個用戶的密碼。通過ssh在Linux服務器上更改密碼的腳本

我試圖找到一個解決方案,但我發現許多腳本都使用Expect。我們的服務器上沒有安裝Expect,系統管理員拒絕讓我們安裝它。另外,用戶沒有root權限,因此無法使用passwd --stdinchpasswd

是否有任何方式可以編寫腳本,以便用戶可以在列表中的所有服務器上運行並更改他自己的用戶的密碼?

+1

更改系統管理員? – TLP

+0

不幸的是沒有一個選項.. :) – squashbuff

回答

16

遠程機器不需要安裝。您可以在本地工作站或虛擬機(virtualbox)或任何* nix盒子上安裝期望,並編寫一個調用此.ex(expect)腳本的包裝器(可能會有一些從發行版到發行版的更改,這在CentOS 5/6上進行了測試):

#!/usr/bin/expect -f 
# wrapper to make passwd(1) be non-interactive 
# username is passed as 1st arg, passwd as 2nd 

set username [lindex $argv 0] 
set password [lindex $argv 1] 
set serverid [lindex $argv 2] 
set newpassword [lindex $argv 3] 

spawn ssh $serverid passwd 
expect "assword:" 
send "$password\r" 
expect "UNIX password:" 
send "$password\r" 
expect "password:" 
send "$newpassword\r" 
expect "password:" 
send "$newpassword\r" 
expect eof 
+0

使用此代碼,你會想讓這段代碼類似./passwdWrapper,然後在你的bash文件中添加 ./passwdWrap $ user $ password $ server $ newpassword – Loren

11

你不需要root權限就可以使用passwd

這應該工作得很好。

passwd <<EOF 
old password 
new password 
new password 
EOF 
+0

謝謝丹尼斯,根據您的文章,密碼一旦用戶登錄到所需的服務器,效果很好。但是,我有一個存儲在servers.txt文件中的服務器列表,我想運行一個腳本,提供一次舊密碼和新密碼,然後該腳本應該在該列表中的所有服務器上更改我的密碼。有什麼想法呢? – squashbuff

+1

'ssh user @ server'command to change password''就是這樣做的。 – Dennis

+0

謝謝丹尼斯,我已經對我的問題進行了編輯,顯示了我所嘗試的內容。目前還沒有,但這是一個好的開始。謝謝.. :) – squashbuff

1

您可能想向同伴展示的​​替代方法是讓他們使用無密碼驗證。他們會生成一個公鑰/私鑰對,並將其公鑰登錄到每個服務器上的〜/ .ssh/authorized_keys文件中。

+0

謝謝,我已經使用公鑰/私鑰進行身份驗證,但即使使用無密碼身份驗證,當密碼在2個月後過期(在我的情況下),我仍然必須登錄到每個服務器,使用「passwd」鍵入舊密碼並輸入兩次新密碼。這有點低效。這就是爲什麼我試圖把這個解決方案放在一起。 – squashbuff

+0

優秀。這簡化了事情。 – phatfingers

+0

你可能在這些服務器上有sudo,對吧?如果您向腳本授予sudo權限以更改其密碼,則該腳本可以使用--stdin參數爲其帳戶運行passwd。 – phatfingers

9

你應該試試pssh(並行ssh在同一時間)。

cat>~/ssh-hosts<<EOF 
[email protected] 
[email protected] 
[email protected] 
EOF 

pssh -h ~/pssh-hosts 'printf "%s\n" old_pass new_pass new_pass | passwd' 
+0

謝謝,這可能是一個很好的解決方案,但是我們的服務器上也沒有pssh .... :( – squashbuff

+0

)您可以在任何發行版本上運行此命令,例如Android設備,筆記本電腦和桌面。安裝它在客戶端,只需要ssh作爲服務器端,我沒有問題;)你可以迭代太簡單需要一個for循環:for i in foo bar base;做ssh「$ i」「命令行」;完成 –

+0

有趣的是,我一定會考慮它。謝謝:) – squashbuff

1

您可以使用Perl嗎?

Here有一個腳本可以更改一組主機中的密碼。

如果需要一些Perl模塊安裝在運行遠程服務器,其中的密碼對劇本,但沒有在本地機器上(Net::OpenSSH::ParallelExpect及其相關性)被改變。

+0

這可能對一些人有用。這是環境設置的特殊方式,限制了我使用這種解決方案。我無法直接從我的客戶機訪問這些服務器。我必須登錄到停用端口轉發的端口。所以腳本需要運行在jumphost上,它具有所有這些限制。謝謝你的信息。 – squashbuff

+0

@squashbuff:我目前正在研究另一個Perl模塊[Net :: OpenSSH :: Gateway](https:// github。com/salva/p5-Net-OpenSSH-Gateway)允許[Net :: OpenSSH](http://search.cpan.org/perldoc?Net::OpenSSH)透明地跳過網關,但它仍然是一項工作進行中。 – salva

0

想我應該把我的解決方案在回答現場 - 不知道這應該是問題的一部分..

OK,我已經把部分工作的解決方案使用丹尼斯的建議。

servers.txt樣子:

server1 
server2 
server3 
. 
. 
. 

我使用:

for server in `cat servers.txt`; do 
ssh $server -l user 'passwd <<EOF 
old_pass 
new_pass 
new_pass 
EOF'; 
done 

這將產生:

[email protected]'s password: **<Type password manually>** 
(current) UNIX password: New UNIX password: Retype new UNIX password: Changing password for user user. 
Changing password for user 
passwd: all authentication tokens updated successfully. 
[email protected]'s password: **<Type password manually>** 
(current) UNIX password: New UNIX password: Retype new UNIX password: Changing password for user user. 
Changing password for user 
passwd: all authentication tokens updated successfully. 

所以在這裏,我還需要鍵入一次我的舊密碼爲每個服務器。這可以避免嗎?

+0

您是否曾經找到避免爲每臺服務器輸入一次舊密碼的方法? – Lizz

+1

@Lizz我結束了使用expect。不是安全方面的理想解決方案,但必須儘快完成。查看Randy Katz接受的答案。 – squashbuff

3

另一種可能性:在一臺服務器上手動更改它。從/ etc/shadow中獲取加密的密碼。現在,做這樣的事情:

for host in $HOST_LIST; do 
    ssh $host "passwd -p 'encrypted_passwd' user" 
done 

當然,「encrypted_pa​​sswd」是你離開了/ etc/shadow文件的,你手動更改了密碼,$ HOST_LIST是你想要的密碼的主機列表。改變。這可能簡單地創建:

export HOST_LIST="server1 server2 server15 server67" 

或許與文件(如其他建議):

export HOST_LIST=`cat host_list.txt` 

凡文件「host_list.txt」擁有所有系統的列表,你想要更改密碼。

編輯:如果你的passwd版本不支持-p選項,你可能有'usermod'程序可用。上面的例子保持不變,只需將'passwd'替換爲'usermod'即可。

此外,你可以考慮useful tool pdsh,這將簡化上述例子是這樣的:

echo $HOST_LIST | pdsh -Rssh -w- "usermod -p 'encrypted_passwd' user" 

最後一個「疑難雜症」看出來的:加密的密碼可能包含美元符號( '$')作爲字段分隔符。您可能必須在for循環或pdsh命令中將其轉義(即「$」變爲「\ $」)。在squashbuff的例子

+1

對於passwd-0.77-4.el6(Enterprise Linux 6)或passwd-0.79-2.fc20(Fedora 20),沒有'-p'選項。 –

+1

看看'usermod'程序...在CentOS(克隆RHEL)5.x和6.x上,它支持-p選項。我編輯了我的回覆以包含更多細節。 – Matt

+0

工作對我很好。只是爲了澄清:您必須轉義您的encrypted_pa​​sswd中的所有$字符,而不是第一個。 – lobi

5

大廈,我嘗試以下,這對我來說效果很好:

#!/bin/bash 
for server in `cat hostlist`; do 
echo $server; 
ssh [email protected]$server 'passwd <&ltEOF 
old_password 
new_password 
new_password 
EOF'; 
done

安全明智的,可以提高取輸入,而不回顯到屏幕或保存明文到磁盤。

0

如果你有ssh,爲什麼要把密碼放在第一位?將用戶的公共ssh密鑰推送到他們有權使用的所有服務器,並完成它。這也讓你輕鬆授予和撤銷所有你想要的訪問權限。

在之前的$ dayjob中,我們擁有數萬臺服務器,他們擁有一個數據庫,哪個工程師可以在哪臺服務器上運行,並且ssh密鑰的安裝是一個自動化過程。幾乎NOBODY在任何機器上都有密碼。

+1

謝謝愛德華,但是基礎設施管理已經外包,我在做出這些決定時沒有任何發言權。我必須在不做大規模的基礎設施變更的情況下完成此項工這不是一個選項。 – squashbuff

4
echo "name:password" | chpasswd 
+2

問題提到'chpasswd'不能使用。 –

2
  1. 上的任何服務器從要執行腳本安裝sshpass

    yum -y install sshpass 
    
  2. 準備中,你必須通過像主機用戶名密碼端口詳細信息的文本文件。 (根據您的要求)。

    192.168.1.2|sachin|dddddd|22 
    
  3. 使用以下詳細信息準備腳本文件。

    #!/bin/bash 
    
    FILE=/tmp/ipaddress.txt 
    
    MyServer="" 
    MyUser="" 
    MyPassword="" 
    MyPort="" 
    
    exec 3<&0 
    exec 0<$FILE 
    
    while read line 
    do 
        MyServer=$(echo $line | cut -d'|' -f1) 
        MyUser=$(echo $line | cut -d'|' -f2) 
        MyPassword=$(echo $line | cut -d'|' -f3) 
        MyPort=$(echo $line | cut -d'|' -f4) 
    
        HOST=$MyServer 
        USR=$MyUser 
        PASS=$MyPassword 
    
        sshpass -p $PASS ssh -p $MyPort -o StrictHostKeychecking=no [email protected]$HOST \ 
          -T "echo '[email protected]' | passwd --stdin root"     \ 
          < /dev/null | tee -a output.log 
    done 
    
    exec 0<&3 
    
+0

如果有人運行'ps',密碼是否可見? –

0

回聲-e 「wakka2 \ nwakka2 \ n」 | passwd root

1

Expect附帶的passmass腳本(man page)不需要Expect安裝在遠程機器上。

-2

真正的問題是爲什麼他們不使用某種名稱服務? NIS /黃頁或LDAP,並且您不必在一堆服務器上手動更改密碼。用戶只需更改一次密碼,然後通過域主服務器完成。

+0

我在目前的環境中工作,已經有了限制。我不是域管理員,我沒有發言權來解決您的解決方案所需的體系結構更改。我正在爲像我這樣的終端用戶在同一個限制性環境中一起提供解決方案。 – squashbuff

0
cat /tmp/passwords | ssh $server sudo chpasswd -e 

如果密碼被加密,或

cat /tmp/passwords | ssh $server sudo chpasswd 

如果密碼沒有被加密。

/tmp /密碼的格式應爲「user:password」

+0

正如問題中提到的,用戶沒有root權限。所以'sudo chpasswd'不能使用。說實話,如果系統管理員允許用戶運行'sudo chpasswd',那麼在我看來這是一個很大的安全問題。 – squashbuff

相關問題