Передача пароля в KLOG из скрипта, используя `subprocess.POPEN` - PullRequest
0 голосов
/ 24 августа 2010

Ряд приложений, которые я пишу, требует, чтобы пользователь мог читать из файловой системы с KLOG аутентификацией. Некоторые функции требуют, чтобы у пользователя были токены KLOG (т.е. проходить аутентификацию), а другие - нет. Я написал небольшой Python-декоратор, чтобы я мог реорганизовать функциональность «вы должны быть KLOGed» в моих модулях:

# this decorator is defined in ``mymodule.utils.decorators``
def require_klog(method):
    def require_klog_wrapper(*args, **kwargs):
        # run the ``tokens`` program to see if we have KLOG tokens
        out = subprocess.Popen('tokens', stdout=subprocess.PIPE)
        # the tokens (if any) are located in lines 4:n-1
        tokens_list = out.stdout.readlines()[3:-1]
        if tokens_list == []:
            # this is where I launch KLOG (if the user is not authenticated)
            subprocess.Popen('klog')
        out = method(*args, **kwargs)
        return out
    return require_klog_wrapper

# once the decorator is defined, any function can use it as follows:
from mymodule.utils.decorators import require_klog
@require_klog
def my_function():
 # do something (if not KLOGed, it SHUOLD ask for the password... but it does not!)

Это все очень просто. За исключением случаев, когда я пытался применить следующую логику: «если пользователь не является KLOGed, запустите KLOG и запросите пароль».

Я делаю это, используя subprocess.Popen('klog'), и приглашение password: подходит к терминалу. Тем не менее, когда я пишу пароль, он на самом деле возвращается в терминал, и, что еще хуже, ничего не происходит при нажатии возврата.

Редактировать:

После быстрого и правильного ответа Алекса я решил проблему следующим образом:

  • Я удалил все файлы *.pyc из каталога моего модуля (да - это имело значение)
  • Я использовал getpass.getpass() для хранения пароля в локальной переменной
  • Я вызвал команду KLOG с опцией -pipe
  • Я передал локально сохраненный пароль в канал с помощью метода write канала

Ниже приведен исправленный декоратор:

def require_klog(method):
    def require_klog_wrapper(*args, **kwargs):
        # run the ``tokens`` program to see if we have KLOG tokens
        out = subprocess.Popen('tokens', stdout=subprocess.PIPE)
        # the tokens (if any) are located in lines 4:n-1
        tokens_list = out.stdout.readlines()[3:-1]
        if tokens_list == []:
            args = ['klog', '-pipe']
            # this is the custom pwd prompt 
            pwd = getpass.getpass('Type in your AFS password: ') 
            pipe = subprocess.Popen(args, stdin=subprocess.PIPE)
            # here is where the password is sent to the program
            pipe.stdin.write(pwd) 
        return method(*args, **kwargs)
    return require_klog_wrapper

1 Ответ

2 голосов
/ 24 августа 2010

Очевидно, ваш скрипт (или что-то еще, что он порождает позже) и подпроцесс, выполняющий klog, "конкурируют" за /dev/tty - и подпроцесс проигрывает (в конце концов, вы не вызываете wait метод объекта, возвращенного из subprocess.Popen, чтобы вы подождали, пока он не прекратит свое действие, прежде чем продолжить, поэтому состояние гонки какого-либо рода вряд ли будет удивительным).

Если wait недостаточно, я бы обошел это, поставив

pwd = getpass.getpass('password:')

в коде Python (с курсом import getpass вверху, конечно), затем klog с аргументом -pipe и stdin=subprocess.PIPE и запись pwd в этот канал (с вызовом сообщить метод объекта, возвращенного из subprocess.Popen).

...