rda-python-common 2.1.10__tar.gz → 2.1.11__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {rda_python_common-2.1.10/src/rda_python_common.egg-info → rda_python_common-2.1.11}/PKG-INFO +4 -4
- {rda_python_common-2.1.10 → rda_python_common-2.1.11}/README.md +1 -1
- {rda_python_common-2.1.10 → rda_python_common-2.1.11}/pyproject.toml +3 -3
- {rda_python_common-2.1.10 → rda_python_common-2.1.11}/src/rda_python_common/__init__.py +1 -1
- {rda_python_common-2.1.10 → rda_python_common-2.1.11}/src/rda_python_common/pg_file.py +18 -9
- {rda_python_common-2.1.10 → rda_python_common-2.1.11}/src/rda_python_common/pg_log.py +8 -10
- {rda_python_common-2.1.10 → rda_python_common-2.1.11}/src/rda_python_common/pg_sig.py +96 -81
- {rda_python_common-2.1.10 → rda_python_common-2.1.11/src/rda_python_common.egg-info}/PKG-INFO +4 -4
- {rda_python_common-2.1.10 → rda_python_common-2.1.11}/src/rda_python_common.egg-info/requires.txt +2 -2
- {rda_python_common-2.1.10 → rda_python_common-2.1.11}/LICENSE +0 -0
- {rda_python_common-2.1.10 → rda_python_common-2.1.11}/setup.cfg +0 -0
- {rda_python_common-2.1.10 → rda_python_common-2.1.11}/src/rda_python_common/PgCMD.py +0 -0
- {rda_python_common-2.1.10 → rda_python_common-2.1.11}/src/rda_python_common/PgDBI.py +0 -0
- {rda_python_common-2.1.10 → rda_python_common-2.1.11}/src/rda_python_common/PgFile.py +0 -0
- {rda_python_common-2.1.10 → rda_python_common-2.1.11}/src/rda_python_common/PgLOG.py +0 -0
- {rda_python_common-2.1.10 → rda_python_common-2.1.11}/src/rda_python_common/PgLock.py +0 -0
- {rda_python_common-2.1.10 → rda_python_common-2.1.11}/src/rda_python_common/PgOPT.py +0 -0
- {rda_python_common-2.1.10 → rda_python_common-2.1.11}/src/rda_python_common/PgSIG.py +0 -0
- {rda_python_common-2.1.10 → rda_python_common-2.1.11}/src/rda_python_common/PgSplit.py +0 -0
- {rda_python_common-2.1.10 → rda_python_common-2.1.11}/src/rda_python_common/PgUtil.py +0 -0
- {rda_python_common-2.1.10 → rda_python_common-2.1.11}/src/rda_python_common/pg_cmd.py +0 -0
- {rda_python_common-2.1.10 → rda_python_common-2.1.11}/src/rda_python_common/pg_dbi.py +0 -0
- {rda_python_common-2.1.10 → rda_python_common-2.1.11}/src/rda_python_common/pg_lock.py +0 -0
- {rda_python_common-2.1.10 → rda_python_common-2.1.11}/src/rda_python_common/pg_opt.py +0 -0
- {rda_python_common-2.1.10 → rda_python_common-2.1.11}/src/rda_python_common/pg_password.py +0 -0
- {rda_python_common-2.1.10 → rda_python_common-2.1.11}/src/rda_python_common/pg_split.py +0 -0
- {rda_python_common-2.1.10 → rda_python_common-2.1.11}/src/rda_python_common/pg_util.py +0 -0
- {rda_python_common-2.1.10 → rda_python_common-2.1.11}/src/rda_python_common/pgpassword.py +0 -0
- {rda_python_common-2.1.10 → rda_python_common-2.1.11}/src/rda_python_common/pgpassword.usg +0 -0
- {rda_python_common-2.1.10 → rda_python_common-2.1.11}/src/rda_python_common.egg-info/SOURCES.txt +0 -0
- {rda_python_common-2.1.10 → rda_python_common-2.1.11}/src/rda_python_common.egg-info/dependency_links.txt +0 -0
- {rda_python_common-2.1.10 → rda_python_common-2.1.11}/src/rda_python_common.egg-info/entry_points.txt +0 -0
- {rda_python_common-2.1.10 → rda_python_common-2.1.11}/src/rda_python_common.egg-info/top_level.txt +0 -0
- {rda_python_common-2.1.10 → rda_python_common-2.1.11}/test/test_common.py +0 -0
{rda_python_common-2.1.10/src/rda_python_common.egg-info → rda_python_common-2.1.11}/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: rda_python_common
|
|
3
|
-
Version: 2.1.
|
|
3
|
+
Version: 2.1.11
|
|
4
4
|
Summary: RDA Python common library codes shared by other RDA python packages
|
|
5
5
|
Author-email: Zaihua Ji <zji@ucar.edu>
|
|
6
6
|
Project-URL: Homepage, https://github.com/NCAR/rda-python-common
|
|
@@ -11,8 +11,8 @@ Classifier: Development Status :: 5 - Production/Stable
|
|
|
11
11
|
Requires-Python: >=3.7
|
|
12
12
|
Description-Content-Type: text/markdown
|
|
13
13
|
License-File: LICENSE
|
|
14
|
-
Requires-Dist:
|
|
15
|
-
Requires-Dist:
|
|
14
|
+
Requires-Dist: psycopg2-binary
|
|
15
|
+
Requires-Dist: psutil
|
|
16
16
|
Requires-Dist: rda-python-globus
|
|
17
17
|
Requires-Dist: unidecode
|
|
18
18
|
Requires-Dist: hvac
|
|
@@ -92,7 +92,7 @@ PgLOG.pglog("hello", PgLOG.LOGWRN)
|
|
|
92
92
|
python -c "import rda_python_common; print(rda_python_common.__version__)"
|
|
93
93
|
```
|
|
94
94
|
|
|
95
|
-
You should see the installed version (currently `2.1.
|
|
95
|
+
You should see the installed version (currently `2.1.11`). If the import
|
|
96
96
|
fails, double-check that the active Python environment is the one where you
|
|
97
97
|
ran `pip install`.
|
|
98
98
|
|
|
@@ -72,7 +72,7 @@ PgLOG.pglog("hello", PgLOG.LOGWRN)
|
|
|
72
72
|
python -c "import rda_python_common; print(rda_python_common.__version__)"
|
|
73
73
|
```
|
|
74
74
|
|
|
75
|
-
You should see the installed version (currently `2.1.
|
|
75
|
+
You should see the installed version (currently `2.1.11`). If the import
|
|
76
76
|
fails, double-check that the active Python environment is the one where you
|
|
77
77
|
ran `pip install`.
|
|
78
78
|
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "rda_python_common"
|
|
7
|
-
version = "2.1.
|
|
7
|
+
version = "2.1.11"
|
|
8
8
|
authors = [
|
|
9
9
|
{ name="Zaihua Ji", email="zji@ucar.edu" },
|
|
10
10
|
]
|
|
@@ -18,8 +18,8 @@ classifiers = [
|
|
|
18
18
|
"Development Status :: 5 - Production/Stable",
|
|
19
19
|
]
|
|
20
20
|
dependencies = [
|
|
21
|
-
"
|
|
22
|
-
"
|
|
21
|
+
"psycopg2-binary",
|
|
22
|
+
"psutil",
|
|
23
23
|
"rda-python-globus",
|
|
24
24
|
"unidecode",
|
|
25
25
|
"hvac"
|
|
@@ -19,6 +19,7 @@ import re
|
|
|
19
19
|
import time
|
|
20
20
|
import glob
|
|
21
21
|
import json
|
|
22
|
+
import hashlib
|
|
22
23
|
from .pg_util import PgUtil
|
|
23
24
|
from .pg_sig import PgSIG
|
|
24
25
|
|
|
@@ -2874,24 +2875,32 @@ class PgFile(PgUtil, PgSIG):
|
|
|
2874
2875
|
(with None for missing files) for multiple files, or None
|
|
2875
2876
|
on failure.
|
|
2876
2877
|
"""
|
|
2877
|
-
cmd = 'md5sum '
|
|
2878
2878
|
if count > 0:
|
|
2879
2879
|
checksum = [None]*count
|
|
2880
2880
|
for i in range(count):
|
|
2881
2881
|
if op.isfile(file[i]):
|
|
2882
|
-
|
|
2883
|
-
if chksm:
|
|
2884
|
-
ms = re.search(r'(\w{32})', chksm)
|
|
2885
|
-
if ms: checksum[i] = ms.group(1)
|
|
2882
|
+
checksum[i] = self._file_md5(file[i], logact)
|
|
2886
2883
|
else:
|
|
2887
2884
|
checksum = None
|
|
2888
2885
|
if op.isfile(file):
|
|
2889
|
-
|
|
2890
|
-
if chksm:
|
|
2891
|
-
ms = re.search(r'(\w{32})', chksm)
|
|
2892
|
-
if ms: checksum = ms.group(1)
|
|
2886
|
+
checksum = self._file_md5(file, logact)
|
|
2893
2887
|
return checksum
|
|
2894
2888
|
|
|
2889
|
+
def _file_md5(self, path, logact=0):
|
|
2890
|
+
"""Compute MD5 hex digest of *path*, reading in 1 MiB chunks.
|
|
2891
|
+
|
|
2892
|
+
Returns the hex digest string, or None on read error.
|
|
2893
|
+
"""
|
|
2894
|
+
try:
|
|
2895
|
+
h = hashlib.md5()
|
|
2896
|
+
with open(path, 'rb') as fh:
|
|
2897
|
+
for chunk in iter(lambda: fh.read(1048576), b''):
|
|
2898
|
+
h.update(chunk)
|
|
2899
|
+
return h.hexdigest()
|
|
2900
|
+
except OSError as e:
|
|
2901
|
+
self.pglog("Error md5sum {}: {}".format(path, str(e)), logact)
|
|
2902
|
+
return None
|
|
2903
|
+
|
|
2895
2904
|
# Evaluate md5 checksums and compare them for two given files
|
|
2896
2905
|
# file1, file2: file names
|
|
2897
2906
|
# Return: 0 if same and 1 if not
|
|
@@ -18,6 +18,7 @@ import grp
|
|
|
18
18
|
import shlex
|
|
19
19
|
import smtplib
|
|
20
20
|
from email.message import EmailMessage
|
|
21
|
+
import subprocess
|
|
21
22
|
from subprocess import Popen, PIPE
|
|
22
23
|
from os import path as op
|
|
23
24
|
import time
|
|
@@ -769,7 +770,7 @@ class PgLOG:
|
|
|
769
770
|
nilcnt = 0
|
|
770
771
|
if begin: sys.stdout.write(line)
|
|
771
772
|
else:
|
|
772
|
-
|
|
773
|
+
subprocess.run(['more', usgname])
|
|
773
774
|
self.pgexit(0)
|
|
774
775
|
|
|
775
776
|
def err2std(self, line):
|
|
@@ -1600,15 +1601,12 @@ class PgLOG:
|
|
|
1600
1601
|
os.environ['MAIL'] = re.sub(self.PGLOG['CURUID'], specialist, os.environ['MAIL'])
|
|
1601
1602
|
home = "{}/{}".format(self.PGLOG['USRHOME'], specialist)
|
|
1602
1603
|
shell = "tcsh"
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
home = ms.group(1)
|
|
1610
|
-
shell = op.basename(ms.group(2))
|
|
1611
|
-
break
|
|
1604
|
+
try:
|
|
1605
|
+
pwent = pwd.getpwnam(specialist)
|
|
1606
|
+
home = pwent.pw_dir
|
|
1607
|
+
shell = op.basename(pwent.pw_shell)
|
|
1608
|
+
except KeyError:
|
|
1609
|
+
pass
|
|
1612
1610
|
if home != os.environ['HOME'] and op.exists(home):
|
|
1613
1611
|
os.environ['HOME'] = home
|
|
1614
1612
|
return shell
|
|
@@ -14,6 +14,8 @@ import sys
|
|
|
14
14
|
import errno
|
|
15
15
|
import signal
|
|
16
16
|
import time
|
|
17
|
+
import subprocess
|
|
18
|
+
import psutil
|
|
17
19
|
from contextlib import contextmanager
|
|
18
20
|
from .pg_dbi import PgDBI
|
|
19
21
|
|
|
@@ -204,6 +206,42 @@ class PgSIG(PgDBI):
|
|
|
204
206
|
self.PGLOG['LOGMASK'] |= self.MSGLOG # turn on logging before daemon stops
|
|
205
207
|
self.pglog("{} Started at {}, Stopped gracefully{} by {}".format(self.PGSIG['DSTR'], self.PGSIG['STRTM'], msg, self.current_datetime()), self.LOGWRN)
|
|
206
208
|
|
|
209
|
+
# scan running processes via psutil and return a list of dicts matching aname/uname
|
|
210
|
+
# Mirrors the semantics of the previous "ps -u U -f | grep A" / "ps -C A -f" pipelines:
|
|
211
|
+
# - with uname: substring match of aname anywhere in cmdline (looser, like grep)
|
|
212
|
+
# - without uname: aname matches the executable basename (with optional .ext)
|
|
213
|
+
# Each entry has keys: 'pid', 'ppid', 'args' ('args' is cmdline[1:] joined).
|
|
214
|
+
def _scan_app_processes(self, aname, uname=None):
|
|
215
|
+
"""Scan running processes matching an application name, optionally by user.
|
|
216
|
+
|
|
217
|
+
Args:
|
|
218
|
+
aname (str): Application name (basename or substring of cmdline).
|
|
219
|
+
uname (str, optional): Username filter.
|
|
220
|
+
|
|
221
|
+
Returns:
|
|
222
|
+
list[dict]: Each dict has keys ``pid``, ``ppid``, ``args``.
|
|
223
|
+
"""
|
|
224
|
+
results = []
|
|
225
|
+
for proc in psutil.process_iter(['pid', 'ppid', 'username', 'cmdline']):
|
|
226
|
+
try:
|
|
227
|
+
info = proc.info
|
|
228
|
+
cmdline = info.get('cmdline') or []
|
|
229
|
+
if not cmdline: continue
|
|
230
|
+
if uname is not None and info.get('username') != uname: continue
|
|
231
|
+
if uname:
|
|
232
|
+
if not any(aname in arg for arg in cmdline): continue
|
|
233
|
+
else:
|
|
234
|
+
exe = os.path.basename(cmdline[0])
|
|
235
|
+
if exe != aname and re.sub(r'\.\w+$', '', exe) != aname: continue
|
|
236
|
+
results.append({
|
|
237
|
+
'pid': info['pid'],
|
|
238
|
+
'ppid': info['ppid'],
|
|
239
|
+
'args': ' '.join(cmdline[1:]),
|
|
240
|
+
})
|
|
241
|
+
except (psutil.NoSuchProcess, psutil.AccessDenied):
|
|
242
|
+
continue
|
|
243
|
+
return results
|
|
244
|
+
|
|
207
245
|
# check if a daemon is running already
|
|
208
246
|
# aname - application name for the daemon
|
|
209
247
|
# uname - user login name who started the daemon
|
|
@@ -218,21 +256,11 @@ class PgSIG(PgDBI):
|
|
|
218
256
|
Returns:
|
|
219
257
|
int: The process ID of the running daemon, or 0 if not running.
|
|
220
258
|
"""
|
|
221
|
-
if uname:
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
pcmd = "ps -C {} -f | grep ' 1 '".format(aname)
|
|
227
|
-
mp = r"^\s*\w+\s+(\d+)\s+1\s+"
|
|
228
|
-
buf = self.pgsystem(pcmd, self.LOGWRN, 20+1024)
|
|
229
|
-
if buf:
|
|
230
|
-
cpid = os.getpid()
|
|
231
|
-
lines = buf.split('\n')
|
|
232
|
-
for line in lines:
|
|
233
|
-
ms = re.match(mp, line)
|
|
234
|
-
pid = int(ms.group(1)) if ms else 0
|
|
235
|
-
if pid > 0 and pid != cpid: return pid
|
|
259
|
+
if uname: self.check_vuser(uname, aname)
|
|
260
|
+
cpid = os.getpid()
|
|
261
|
+
for p in self._scan_app_processes(aname, uname):
|
|
262
|
+
if p['ppid'] != 1: continue
|
|
263
|
+
if p['pid'] != cpid: return p['pid']
|
|
236
264
|
return 0
|
|
237
265
|
|
|
238
266
|
# check if an application is running already; other than the current processs
|
|
@@ -251,31 +279,21 @@ class PgSIG(PgDBI):
|
|
|
251
279
|
Returns:
|
|
252
280
|
int: The process ID of the running instance, or 0 if not found.
|
|
253
281
|
"""
|
|
254
|
-
if uname:
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
mp = r"^\s*{}\s+(\d+)\s+(\d+)\s+.*{}\S*\s+(.*)$".format(uname, aname)
|
|
258
|
-
else:
|
|
259
|
-
pcmd = "ps -C {} -f".format(aname)
|
|
260
|
-
mp = r"^\s*\w+\s+(\d+)\s+(\d+)\s+.*{}\S*\s+(.*)$".format(aname)
|
|
261
|
-
buf = self.pgsystem(pcmd, self.LOGWRN, 20+1024)
|
|
262
|
-
if not buf: return 0
|
|
282
|
+
if uname: self.check_vuser(uname, aname)
|
|
283
|
+
procs = self._scan_app_processes(aname, uname)
|
|
284
|
+
if not procs: return 0
|
|
263
285
|
cpids = [os.getpid(), os.getppid()]
|
|
264
286
|
pids = []
|
|
265
287
|
ppids = []
|
|
266
288
|
astrs = []
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
ms = re.match(mp, line)
|
|
270
|
-
if not ms: continue
|
|
271
|
-
pid = int(ms.group(1))
|
|
272
|
-
ppid = int(ms.group(2))
|
|
289
|
+
for p in procs:
|
|
290
|
+
pid, ppid = p['pid'], p['ppid']
|
|
273
291
|
if pid in cpids:
|
|
274
292
|
if ppid not in cpids: cpids.append(ppid)
|
|
275
293
|
continue
|
|
276
294
|
pids.append(pid)
|
|
277
295
|
ppids.append(ppid)
|
|
278
|
-
if sargv: astrs.append(
|
|
296
|
+
if sargv: astrs.append(p['args'])
|
|
279
297
|
pcnt = len(pids)
|
|
280
298
|
if not pcnt: return 0
|
|
281
299
|
i = 0
|
|
@@ -329,25 +347,15 @@ class PgSIG(PgDBI):
|
|
|
329
347
|
Returns:
|
|
330
348
|
int: Number of running instances (excluding the current process).
|
|
331
349
|
"""
|
|
332
|
-
if uname:
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
mp = r"^\s*{}\s+(\d+)\s+(\d+)\s+.*{}\S*\s+(.*)$".format(uname, aname)
|
|
336
|
-
else:
|
|
337
|
-
pcmd = "ps -C {} -f".format(aname)
|
|
338
|
-
mp = r"^\s*\w+\s+(\d+)\s+(\d+)\s+.*{}\S*\s+(.*)$".format(aname)
|
|
339
|
-
buf = self.pgsystem(pcmd, self.LOGWRN, 20+1024)
|
|
340
|
-
if not buf: return 0
|
|
350
|
+
if uname: self.check_vuser(uname, aname)
|
|
351
|
+
procs = self._scan_app_processes(aname, uname)
|
|
352
|
+
if not procs: return 0
|
|
341
353
|
dpids = [os.getpid(), os.getppid()]
|
|
342
354
|
pids = []
|
|
343
355
|
ppids = []
|
|
344
356
|
astrs = []
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
ms = re.match(mp, line)
|
|
348
|
-
if not ms: continue
|
|
349
|
-
pid = int(ms.group(1))
|
|
350
|
-
ppid = int(ms.group(2))
|
|
357
|
+
for p in procs:
|
|
358
|
+
pid, ppid = p['pid'], p['ppid']
|
|
351
359
|
if pid in dpids:
|
|
352
360
|
if ppid > 1 and ppid not in dpids: dpids.append(ppid)
|
|
353
361
|
continue
|
|
@@ -356,7 +364,7 @@ class PgSIG(PgDBI):
|
|
|
356
364
|
continue
|
|
357
365
|
pids.append(pid)
|
|
358
366
|
ppids.append(ppid)
|
|
359
|
-
if sargv: astrs.append(
|
|
367
|
+
if sargv: astrs.append(p['args'])
|
|
360
368
|
pcnt = len(pids)
|
|
361
369
|
if not pcnt: return 0
|
|
362
370
|
i = 0
|
|
@@ -627,18 +635,20 @@ class PgSIG(PgDBI):
|
|
|
627
635
|
list: PIDs of processes that were successfully killed.
|
|
628
636
|
"""
|
|
629
637
|
if logact is None: logact = self.LOGWRN
|
|
630
|
-
buf = self.pgsystem("ps --ppid {} -o pid".format(pid), logact, 20)
|
|
631
638
|
pids = []
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
639
|
+
try:
|
|
640
|
+
children = psutil.Process(pid).children()
|
|
641
|
+
except psutil.NoSuchProcess:
|
|
642
|
+
children = []
|
|
643
|
+
except Exception as e:
|
|
644
|
+
self.pglog("Error listing children of pid {}: {}".format(pid, str(e)), logact)
|
|
645
|
+
children = []
|
|
646
|
+
for child in children:
|
|
647
|
+
cid = child.pid
|
|
648
|
+
if not self.check_process(cid): continue
|
|
649
|
+
cids = self.kill_children(cid, logact)
|
|
650
|
+
if cids: pids = cids + pids
|
|
651
|
+
if self.kill_process(cid, signal.SIGKILL, logact) == self.SUCCESS: pids.insert(0, cid)
|
|
642
652
|
if logact and len(pids): self.pglog("Process({}) Killed".format(','.join(map(str, pids))), logact)
|
|
643
653
|
return pids
|
|
644
654
|
|
|
@@ -808,13 +818,11 @@ class PgSIG(PgDBI):
|
|
|
808
818
|
Returns:
|
|
809
819
|
int: 1 if the process is running, 0 otherwise.
|
|
810
820
|
"""
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
if re.match(mp, line): return 1
|
|
817
|
-
return 0
|
|
821
|
+
try:
|
|
822
|
+
os.kill(pid, 0)
|
|
823
|
+
except OSError:
|
|
824
|
+
return 0
|
|
825
|
+
return 1
|
|
818
826
|
|
|
819
827
|
# check a process id on give host
|
|
820
828
|
def check_host_pid(self, host, pid, pmsg=None, logact=None):
|
|
@@ -1092,7 +1100,10 @@ class PgSIG(PgDBI):
|
|
|
1092
1100
|
self.PGLOG['ERRFILE'] = re.sub(r'\.log$', '.err', self.PGLOG['LOGFILE'], 1)
|
|
1093
1101
|
bckcmd += " 2>> {}/{}".format(self.PGLOG['LOGPATH'], self.PGLOG['ERRFILE'])
|
|
1094
1102
|
bckcmd += " &"
|
|
1095
|
-
|
|
1103
|
+
# shell=True is required for the redirections (>> / 2>>) and trailing '&';
|
|
1104
|
+
# the '&' makes the shell fork the command and exit, so the command gets
|
|
1105
|
+
# reparented to init (ppid=1), matching the lookup logic in record_background().
|
|
1106
|
+
subprocess.Popen(bckcmd, shell=True)
|
|
1096
1107
|
return self.record_background(cmd, logact)
|
|
1097
1108
|
|
|
1098
1109
|
# get background process id for given bcmd
|
|
@@ -1170,27 +1181,31 @@ class PgSIG(PgDBI):
|
|
|
1170
1181
|
"""
|
|
1171
1182
|
if logact is None: logact = self.LOGWRN
|
|
1172
1183
|
ms = re.match(r'^(\S+)', bcmd)
|
|
1173
|
-
if ms
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
aname = bcmd
|
|
1177
|
-
mp = r"^\s*(\S+)\s+(\d+)\s+1\s+.*{}(.*)$".format(aname)
|
|
1178
|
-
pc = "ps -u {},{} -f | grep ' 1 ' | grep {}".format(self.PGLOG['CURUID'], self.PGLOG['GDEXUSER'], aname)
|
|
1184
|
+
aname = ms.group(1) if ms else bcmd
|
|
1185
|
+
curuid = self.PGLOG['CURUID']
|
|
1186
|
+
gdexuser = self.PGLOG['GDEXUSER']
|
|
1179
1187
|
for i in range(2):
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
if
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
+
for proc in psutil.process_iter(['pid', 'ppid', 'username', 'cmdline']):
|
|
1189
|
+
try:
|
|
1190
|
+
info = proc.info
|
|
1191
|
+
if info.get('ppid') != 1: continue
|
|
1192
|
+
uid = info.get('username')
|
|
1193
|
+
if uid != curuid and uid != gdexuser: continue
|
|
1194
|
+
cmdline = info.get('cmdline') or []
|
|
1195
|
+
if not cmdline: continue
|
|
1196
|
+
line = ' '.join(cmdline)
|
|
1197
|
+
idx = line.find(aname)
|
|
1198
|
+
if idx < 0: continue
|
|
1199
|
+
bid = info['pid']
|
|
1188
1200
|
if bid in self.CBIDS: return -1
|
|
1189
|
-
|
|
1201
|
+
acmd = line[idx+len(aname):]
|
|
1202
|
+
if uid == gdexuser:
|
|
1190
1203
|
acmd = re.sub(r'^\.(pl|py)\s+', '', acmd, 1)
|
|
1191
1204
|
if re.match(r'^{}{}'.format(aname, acmd), bcmd): continue
|
|
1192
1205
|
self.CBIDS[bid] = bcmd
|
|
1193
1206
|
return 1
|
|
1207
|
+
except (psutil.NoSuchProcess, psutil.AccessDenied):
|
|
1208
|
+
continue
|
|
1194
1209
|
time.sleep(2)
|
|
1195
1210
|
return 0
|
|
1196
1211
|
|
{rda_python_common-2.1.10 → rda_python_common-2.1.11/src/rda_python_common.egg-info}/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: rda_python_common
|
|
3
|
-
Version: 2.1.
|
|
3
|
+
Version: 2.1.11
|
|
4
4
|
Summary: RDA Python common library codes shared by other RDA python packages
|
|
5
5
|
Author-email: Zaihua Ji <zji@ucar.edu>
|
|
6
6
|
Project-URL: Homepage, https://github.com/NCAR/rda-python-common
|
|
@@ -11,8 +11,8 @@ Classifier: Development Status :: 5 - Production/Stable
|
|
|
11
11
|
Requires-Python: >=3.7
|
|
12
12
|
Description-Content-Type: text/markdown
|
|
13
13
|
License-File: LICENSE
|
|
14
|
-
Requires-Dist:
|
|
15
|
-
Requires-Dist:
|
|
14
|
+
Requires-Dist: psycopg2-binary
|
|
15
|
+
Requires-Dist: psutil
|
|
16
16
|
Requires-Dist: rda-python-globus
|
|
17
17
|
Requires-Dist: unidecode
|
|
18
18
|
Requires-Dist: hvac
|
|
@@ -92,7 +92,7 @@ PgLOG.pglog("hello", PgLOG.LOGWRN)
|
|
|
92
92
|
python -c "import rda_python_common; print(rda_python_common.__version__)"
|
|
93
93
|
```
|
|
94
94
|
|
|
95
|
-
You should see the installed version (currently `2.1.
|
|
95
|
+
You should see the installed version (currently `2.1.11`). If the import
|
|
96
96
|
fails, double-check that the active Python environment is the one where you
|
|
97
97
|
ran `pip install`.
|
|
98
98
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{rda_python_common-2.1.10 → rda_python_common-2.1.11}/src/rda_python_common.egg-info/SOURCES.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{rda_python_common-2.1.10 → rda_python_common-2.1.11}/src/rda_python_common.egg-info/top_level.txt
RENAMED
|
File without changes
|
|
File without changes
|