77from shutil import rmtree
88from signal import signal , SIGINT , SIGTERM , SIG_IGN
99from subprocess import Popen , PIPE
10+ from time import sleep
1011
1112from mongodb_consistent_backup .Common import is_datetime
1213from mongodb_consistent_backup .Oplog import Oplog
@@ -30,9 +31,12 @@ def __init__(self, state, uri, timer, user, password, authdb, base_dir, binary,
3031 self .dump_gzip = dump_gzip
3132 self .verbose = verbose
3233
33- self .timer_name = "%s-%s" % (self .__class__ .__name__ , self .uri .replset )
34- self .exit_code = 1
35- self ._command = None
34+ self .timer_name = "%s-%s" % (self .__class__ .__name__ , self .uri .replset )
35+ self .exit_code = 1
36+ self ._command = None
37+ self .do_stdin_passwd = False
38+ self .stdin_passwd_sent = False
39+
3640 self .backup_dir = os .path .join (self .base_dir , self .uri .replset )
3741 self .dump_dir = os .path .join (self .backup_dir , "dump" )
3842 self .oplog_file = os .path .join (self .dump_dir , "oplog.bson" )
@@ -61,6 +65,18 @@ def parse_mongodump_line(self, line):
6165 except :
6266 return None
6367
68+ def is_password_prompt (self , line ):
69+ if self .do_stdin_passwd and ("Enter Password:" in line or "reading password from standard input" in line ):
70+ return True
71+ return False
72+
73+ def handle_password_prompt (self ):
74+ if self .do_stdin_passwd and not self .stdin_passwd_sent :
75+ logging .debug ("Received password prompt from mongodump, writing password to stdin" )
76+ self ._process .stdin .write (self .password + "\n " )
77+ self ._process .stdin .flush ()
78+ self .stdin_passwd_sent = True
79+
6480 def wait (self ):
6581 try :
6682 while self ._process .stderr :
@@ -69,7 +85,11 @@ def wait(self):
6985 for fd in poll [0 ]:
7086 read = self ._process .stderr .readline ()
7187 line = self .parse_mongodump_line (read )
72- if line :
88+ if not line :
89+ continue
90+ elif self .is_password_prompt (read ):
91+ self .handle_password_prompt ()
92+ else :
7393 logging .info (line )
7494 if self ._process .poll () != None :
7595 break
@@ -92,7 +112,12 @@ def mongodump_cmd(self):
92112 logging .debug ("Using database %s for authentication" % self .authdb )
93113 mongodump_flags .extend (["--authenticationDatabase" , self .authdb ])
94114 if self .user and self .password :
95- mongodump_flags .extend (["-u" , self .user , "-p" , self .password ])
115+ # >= 3.0.2 supports password input via stdin to mask from ps
116+ if tuple ("3.0.2" .split ("." )) <= tuple (self .version .split ("." )):
117+ mongodump_flags .extend (["-u" , self .user , "-p" , '""' ])
118+ self .do_stdin_passwd = True
119+ else :
120+ mongodump_flags .extend (["-u" , self .user , "-p" , self .password ])
96121 mongodump_cmd .extend (mongodump_flags )
97122 return mongodump_cmd
98123
@@ -109,7 +134,12 @@ def run(self):
109134 rmtree (self .dump_dir )
110135 os .makedirs (self .dump_dir )
111136 logging .debug ("Running mongodump cmd: %s" % mongodump_cmd )
112- self ._process = Popen (mongodump_cmd , stderr = PIPE )
137+ self ._process = Popen (mongodump_cmd , stdin = PIPE , stderr = PIPE )
138+ #if self.do_stdin_passwd:
139+ # sleep(5)
140+ # logging.debug("Writing password to stdin")
141+ # self._process.stdin.write(self.password)
142+ # self._process.stdin.flush()
113143 self .wait ()
114144 self .exit_code = self ._process .returncode
115145 if self .exit_code > 0 :
0 commit comments