Как мне запустить Perl-скрипт из bash, используя аргументы командной строки?

Я пытаюсь создать скрипт для пакетной маркировки группы пользователей как привилегированных в RT. В вики RT я нашел скрипт для добавления пользователей в группу и присвоения им привилегированного статуса, а затем удалил его кусочки, связанные с добавлением в группу. У меня есть оставшийся скрипт на Perl:

#!/usr/bin/perl
# Usage: ./rt_set_privileged.pl <username>

use strict;
use lib "/var/www/ticket.ourcompany.com/lib";
use RT;
use RT::User;
use RT::Interface::CLI;

RT::LoadConfig();
RT::Init();

# Create RT User Object
my $user = new RT::User($RT::SystemUser);

# Instantiate the user object with the user passed as parameter
my $usertoadd = $ARGV[0];
$user->Load( $usertoadd );

# Set the privileged flag (1=privileged, 0=unprivileged)
$user->SetPrivileged(1);

exit 1

У меня есть пользователи в файле, одно имя пользователя в строке. Я пока не знаю perl, поэтому я попытался создать небольшой скрипт bash, чтобы пройтись по файлу и запустить скрипт perl один раз для каждого имени. Скрипт Bash, как он выглядит прямо сейчас:

#!/bin/bash

touch commands.sh
cat usernames.txt | while read LINE ; do
        N=$((N+1))
        echo /home/chris/RT/bin/rt_set_privileged.pl \"$LINE\" >> commands.sh
        /home/chris/RT/bin/rt_set_privileged.pl \"$LINE\"
        perl /home/chris/RT/bin/rt_set_privileged.pl \"$LINE\"
        perl -w /home/chris/RT/bin/rt_set_privileged.pl \"$LINE\"
        eval /home/chris/RT/bin/rt_set_privileged.pl \"$LINE\"
        perl "/home/chris/RT/bin/rt_set_privileged.pl $LINE"
done
echo "Processed $N users"

Как вы можете видеть, я пытался использовать несколько методов для запуска команды, но безрезультатно. Раздражает то, что я могу потом взять любую из команд из файла command.sh и без проблем вставить их прямо в терминал, это прекрасно работает. Когда они запускаются через скрипт bash, я просто получаю кучу этих сообщений:

[Tue Sep  4 07:43:56 2012] [critical]: _AddMember called with a parameter that's not an integer. (/var/www/ticket.ourcompany.com/lib/RT/Group.pm:912)
[Tue Sep  4 07:43:58 2012] [warning]: Use of uninitialized value $principal in pattern match (m//) at /var/www/ticket.ourcompany.com/lib/RT/Group.pm line 970. (/var/www/ticket.ourcompany.com/lib/RT/Group.pm:968)
[Tue Sep  4 07:43:58 2012] [error]: Group::HasMember was called with an argument that isn't an RT::Principal or id. It's (undefined) (/var/www/ticket.ourcompany.com/lib/RT/Group.pm:973)
[Tue Sep  4 07:43:58 2012] [warning]: Use of uninitialized value $principal in pattern match (m//) at /var/www/ticket.ourcompany.com/lib/RT/Group.pm line 970. (/var/www/ticket.ourcompany.com/lib/RT/Group.pm:968)
[Tue Sep  4 07:43:58 2012] [error]: Group::HasMember was called with an argument that isn't an RT::Principal or id. It's (undefined) (/var/www/ticket.ourcompany.com/lib/RT/Group.pm:973)
[Tue Sep  4 07:43:58 2012] [warning]: Use of uninitialized value in concatenation (.) or string at /var/www/ticket.ourcompany.com/lib/RT/User.pm line 341. (/var/www/ticket.ourcompany.com/lib/RT/User.pm:341)
[Tue Sep  4 07:43:58 2012] [critical]: User  is neither privileged nor unprivileged. something is drastically wrong. (/var/www/ticket.ourcompany.com/lib/RT/User.pm:341)
[Tue Sep  4 07:43:58 2012] [warning]: Use of uninitialized value $new_member in pattern match (m//) at /var/www/ticket.ourcompany.com/lib/RT/Group.pm line 911. (/var/www/ticket.ourcompany.com/lib/RT/Group.pm:911)

предполагая, что команда выполняется без каких-либо параметров. В этот момент я мог бы запустить команду по одному разу для каждого пользователя за то время, пока я пытался ее решить, кто-нибудь может помочь?

5 ответов

Решение

Аааа, мне грустно, что мне понадобилось так много времени, чтобы понять такую ​​простую проблему. Проблема заключалась в форматировании строки - файл usernames.txt был создан кем-то с помощью Windows и имел форматирование DOS (CRLF). Я предполагаю, что аргумент прибыл как [username][LF] и испортил создание экземпляра переменной $User.

Я уверен, что никогда бы не получил это, не приехав сюда, чтобы обсудить это, я ходил кругами, просто пробуя сам.

Резолюция была просто:

sudo apt-get install tofrodos
sudo fromdos usernames.txt

И тогда оригинальный сценарий работал

Большое спасибо за помощь, ребята.

Редактировать: прошло достаточно времени, чтобы я перешел от редактирования исходного вопроса к его собственному ответу

В этом коде Perl есть куча ошибок программирования - все сообщения об ошибках, которые вы получаете, являются сообщениями компилятора. Таким образом, вызов правильный, но код Perl неправильный.

То, что вы хотите сделать, это редактировать код Perl, пока все сообщения об ошибках и предупреждения не исчезнут.

Изменить: Perl-код является неправильным в среде, в которой он работает в то время.

perl /home/chris/RT/bin/rt_set_privileged.pl "$LINE"

Если файл был сделан исполняемым, вы также можете сделать:

/home/chris/RT/bin/rt_set_privileged.pl "$LINE"

Например,

$ cat usernames.txt 
ikegami
Chris O'Kelly

$ cat script.pl 
#!/usr/bin/env perl
print "arg=<<$ARGV[0]>>\n";

$ while read LINE ; do script.pl "$LINE"; done <usernames.txt
arg=<<ikegami>>
arg=<<Chris O'Kelly>>

Вы могли бы использовать xargs вместо while read:

$ xargs -n1 -d\\n script.pl <usernames.txt 
arg=<<ikegami>>
arg=<<Chris O'Kelly>>

Другое решение: не используйте bash-скрипт, а непосредственно отредактируйте perl-скрипт, откройте файл usernames.txt и прочитайте его построчно - это тоже решит вашу проблему.

Как здесь http://www.perlfect.com/articles/perlfile.shtml:

my $file = "usernames.txt";
open USERS, "<$file" or die "Can't open $file ($!)";

while(<USERS>) {
 my $usertoadd = $_;
 chomp $usertoadd;
 $user->Load( $usertoadd );
 $user->SetPrivileged(1);
}

ОБНОВЛЕНИЕ: теперь учитывается возможность пробелов в именах пользователей, благодаря ценному совету из блога Peniwize.

OLD_IFS=$IFS
IFS=$'\n'    
priveleged=( $( cat usernames.txt) )
for i in "${priveleged[@]}"
do
    perl /home/chris/RT/bin/rt_set_privileged.pl $i
done
IFS=$OLD_IFS
Другие вопросы по тегам