我正在编写一个程序,根据我们公司的政策添加正常的UNIX帐户(即修改/ etc / passwd,/ etc / group和/ etc / shadow)。它还会做一些有点花哨的事情,例如向用户发送电子邮件。
我已经完成了所有代码,但有三段非常关键的代码,它们会更新上面的三个文件。代码已经相当健壮,因为它锁定了这些文件(例如/etc/passwd.lock),写入临时文件(例如/etc/passwd.tmp),然后用临时文件覆盖原始文件。我很高兴它不会干扰我的程序的其他运行版本或系统useradd,usermod,passwd等程序。
我最担心的是在这些部分的中间有一个迷路ctrl + c,ctrl + d或kill命令。这让我进入了信号模块,它似乎正是我想要的:在“关键”区域内忽略某些信号。 我正在使用旧版本的Python,它没有signal.SIG_IGN,所以我有一个很棒的“传递”功能:
def passer(*a):
pass
我看到的问题是信号处理程序无法按照我的预期运行。 给出以下测试代码:
def passer(a=None, b=None):
pass
def signalhander(enable):
signallist = (signal.SIGINT, signal.SIGQUIT, signal.SIGABRT, signal.SIGPIPE, signal.SIGALRM, signal.SIGTERM, signal.SIGKILL)
if enable:
for i in signallist:
signal.signal(i, passer)
else:
for i in signallist:
signal.signal(i, abort)
return
def abort(a=None, b=None):
sys.exit('\nAccount was not created.\n')
return
signalhander(True)
print('Enabled')
time.sleep(10) # ^C during this sleep
此代码的问题是在time.sleep(10)调用期间^ C(SIGINT)导致该函数停止,然后,我的信号处理程序将根据需要接管。但是,这并没有解决我上面的“关键”区域问题,因为我不能容忍遇到信号失败的任何语句。
我需要某种信号处理程序,它将完全忽略SIGINT和SIGQUIT。 Fedora / RH命令“yum”是用Python编写的,基本上完全符合我的要求。如果你在安装任何东西的时候做了^ C,它会打印一条消息,比如“在两秒钟内按下^ C强行杀死”。否则,忽略^ C.因为我的程序在几分之一秒内完成,所以我并不关心第二次警告。
有人可以帮我实现CPython 2.3的信号处理程序,在信号被忽略之前不会导致当前语句/函数被取消吗?
一如既往,提前谢谢。
编辑:在S.Lott回答之后,我决定放弃信号模块。
我要回到try: except:
块。查看我的代码,每个关键区域都会发生两件无法中止的事情:使用file.tmp覆盖文件并在完成后删除锁定(或者其他工具将无法修改文件,直到手动删除)。我将其中的每一个放在try:
块中的自己的函数中,而except:
只是再次调用该函数。这样,该函数将在KeyBoardInterrupt
或EOFError
的情况下重新调用自身,直到关键代码完成。
我不认为我会遇到太多麻烦,因为我只捕获用户提供的退出命令,即便如此,只有两到三行代码。从理论上讲,如果能够足够快地提高这些例外情况,我想我可以得到“最大复发深度超出”错误,但这似乎很遥远。
还有其他问题吗?
04-0030-03代码:
def criticalRemoveLock(file):
try:
if os.path.isFile(file):
os.remove(file)
else:
return True
except (KeyboardInterrupt, EOFError):
return criticalRemoveLock(file)
def criticalOverwrite(tmp, file):
try:
if os.path.isFile(tmp):
shutil.copy2(tmp, file)
os.remove(tmp)
else:
return True
except (KeyboardInterrupt, EOFError):
return criticalOverwrite(tmp, file)
答案 0 :(得分:3)
没有真正的方法可以让您的脚本真正保存。当然,您可以使用try: except:
忽略信号并捕获键盘中断,但是您的应用程序可以对这些中断进行幂等,并且必须能够在某种保存点处理中断后恢复操作。
你唯一能做的就是处理临时文件(而不是原始文件)并在完成最终目的地之后移动它们。我认为这样的文件操作应该是" atomic"从文件系统的角度来看。否则,如果发生中断:从干净的数据开始重新开始处理。