Windows Server 2008 R2. Новые возможности служб AD DS Александр Емельянов djoin.exe /provision /domain имя_целевого_домена /machine имя_компьютера /dcname имя_контроллера_домена [/downlevel] /savefile c:\blob.txt djoin.exe /requestODJ /loadfile c:\blob.txt /windowspath %SystemRoot% /localos ----------------------------------------------------------------------------------------------------------------- Мониторинг состояния температурных датчиков с помощью протокола SNMP Вадим Шпурик $ cd ~ $ mkdir sensTable $ cd sensTable $ env MIBS="/usr/share/snmp/mibs/SENSOR-MIB.mib.txt" mib2c -c mib2c.mfd.conf \ sensTable $ grep -n "TODO:" *.[ch] | sed 's/\([^ ]*\)\(.*\)TODO\(.*\)/\3 (\1)/' | sort -n $ snmptranslate -m /usr/share/snmp/mibs/SENSOR-MIB.mib.txt -Tp -IR sensTable 1,"Sensor 241",1,"22.6",226,0,14991,0 1,"Sensor 241",1,"22.6",226,0,14991,0 2,"Sensor 242",1,"11.4",114,0,14992,0 3,"Sensor 243",1,"2.2",22,0,14993,0 4,"Sensor 244",1,"21.5",215,0,14994,0 5,"Sensor 245",1,"20.6",206,0,14995,0 6,"Sensor 246",1,"24.0",240,0,14996,0 #!/bin/bash CSVPATH="/home/snmp/sensTable/" CSVFILE=${CSVPATH}"sensor.csv" SENSOR[1]="1,\"Sensor 241\",1,\"24.5\",245,0,14991,0" SENSOR[2]="2,\"Sensor 242\",1,\"36.6\",366,0,14992,0" SENSOR[3]="3,\"Sensor 243\",1,\"12.2\",122,0,14993,0" SENSOR[4]="4,\"Sensor 244\",1,\"21.5\",215,0,14994,0" SENSOR[5]="5,\"Sensor 245\",1,\"20.6\",206,0,14995,0" SENSOR[6]="6,\"Sensor 246\",1,\"31.7\",317,0,14996,0" if [ ! -f ${CSVFILE} ] then for index in 1 2 3 4 5 6 # Six lines. do printf "%s\n" "${SENSOR[index]}" >> ${CSVFILE} done else cat $CSVFILE | awk -F"," ' BEGIN { srand(systime()) # [min,max] values SENS[1] = "21,34" # 21.0 .. 34.9 SENS[2] = "10,15" # 10.0 .. 15.9 SENS[3] = "1,6" # 1.0 .. 6.9 SENS[4] = "0,0" # do nothing SENS[5] = "0,0" # do nothing SENS[6] = "23,29" # 23.0 .. 29.9 } function randint(n) { return int(n * rand()) } { split(SENS[NR], temp, ",") min = temp[1] max = temp[2] if (min == max) { SENS[NR] = $0 } else { grad = min + randint(max-min) fraction = randint(9) split($0, sens, ",") gsub("\"", "", sens[2]) SENS[NR] = sprintf("%s,\"%s\",%s,\"%d.%1d\",%d%1d,%s,%s,%s", sens[1],sens[2],sens[3], grad,fraction,grad,fraction, sens[6],sens[7],sens[8]) } } END { for (x in SENS) { printf "%s\n", SENS[x] | "sort > '$CSVFILE'" } }' fi $ crontab -e SHELL=/bin/bash */10 * * * * /home/snmp/sensTable/sensor.sh > /dev/null 2>&1 $ diff sensTable_data_access.c.orig sensTable_data_access.c > patchfile.patch $ patch sensTable_data_access.c.orig -i patchfile.patch -o sensTable_data_access.c $ make -f sensTable_Makefile $ net-snmp-config --base-cflags $ net-snmp-config --agent-libs $ ldd sensTable # service snmpd start # ps fax | grep snmpd | grep -v grep # cd /home/snmp/sensTable # ./sensTable -f -DsensTable,verbose:sensTable,internal:sensTable # ./sensTable -f & # ps fax | grep sensTable | grep -v grep # snmpwalk -v2c localhost -c public .1.3.6.1.4.1.21796.3.3.3 # snmpwalk -v2c localhost -c public .1.3.6.1.4.1.21796.3.3.3.1.2 # snmpwalk -v2c localhost -c public .1.3.6.1.4.1.21796.3.3.3.1.6.1 cfg_file=/etc/nagios/objects/switch.cfg define host{ use generic-switch host_name poseidon alias Poseidon 3262 address 127.0.0.1 hostgroups switches } define hostgroup{ hostgroup_name switches alias Network Switches } define service{ use generic-service host_name poseidon service_description Sensor_1 check_command check_snmp!-C public -o .1.3.6.1.4.1.21796.3.3.3.1.5.1 } define service{ use generic-service host_name poseidon service_description Sensor_2 check_command check_snmp!-C public -o .1.3.6.1.4.1.21796.3.3.3.1.5.2 } define service{ use generic-service host_name poseidon service_description Sensor_3 check_command check_snmp!-C public -o .1.3.6.1.4.1.21796.3.3.3.1.5.3 } define service{ use generic-service host_name poseidon service_description Sensor_4 check_command check_snmp!-C public -o .1.3.6.1.4.1.21796.3.3.3.1.5.4 } define service{ use generic-service host_name poseidon service_description Sensor_5 check_command check_snmp!-C public -o .1.3.6.1.4.1.21796.3.3.3.1.5.5 } define service{ use generic-service host_name poseidon service_description Sensor_6 check_command check_snmp!-C public -o .1.3.6.1.4.1.21796.3.3.3.1.5.6 } ----------------------------------------------------------------------------------------------------------------- Веб-топ-решение на основе Ulteo Virtual Desktop Антон Борисов Листинг 1. Пример конфигурационного файла Windows-агента Ulteo SERVERNAME=10.10.250.10 SESSION_MANAGER_URL=http://10.10.2.10/sessionmanager LOG_FLAGS="info warn error" WEBPORT=8082 1) switch ($prefs->get('UserDB', 'enable')) { 2) case 'activedirectory': 3) $prefs_ad = $prefs->get('UserDB', 'activedirectory'); 4) $windows_login = $user->getAttribute('real_login').'@'.$prefs_ad['domain']; 6) break; 7) case 'ldap': 8) $prefs_ldap = $prefs->get('UserDB', 'ldap'); 9) if ($prefs_ldap['ad'] == 1) { 10) $buf = $prefs_ldap['suffix']; 11) $suffix = suffix2domain($buf); 12) if (! is_string($suffix)) { 13) Logger::error('main', 'LDAP suffix is invalid for AD usage : '.$buf); 14) break; 15) } 16) $windows_login = $user->getAttribute('login').'@'.$suffix; 17) } 18) break; 19) default: 20) $windows_login = $user->getAttribute('login'); 21) break; 22) } ----------------------------------------------------------------------------------------------------------------- Веб-топ-решение на основе Ulteo Virtual Desktop Антон Борисов # mke2fs -j /media/hda1 # umount /media/hda1 # mount –o rw /media/hda1 # mkdir /media/hda1/knoppix # df -h /media/hda1 # free –m # dd if=/dev/zero of=/media/hda1/knoppix/myswap bs=1M count=1000 # mkswap /media/hda1/knoppix/myswap # chmod 0600 /media/hda1/knoppix/myswap # swapon /media/hda1/knoppix/myswap # mkdir -p /media/hda1/knoppix/master/KNOPPIX # mkdir -p /media/hda1/knoppix/source/KNOPPIX # cp -Rp /KNOPPIX/* /media/hda1/knoppix/source/KNOPPIX # cp /cdrom/index.html /media/hda1/knoppix/master # cp /cdrom/autorun.* /media/hda1/knoppix/master # cp /cdrom/cdrom.ico /media/hda1/knoppix/master # cp /cdrom/KNOPPIX && find . -size -10000k -type f -exec cp -p -parents '[]' /media/hda1/knoppix/master/KNOPPIX/ \; # chroot /media/hda1/knoppix/source/KNOPPIX # mount -t proc /proc proc # dpkg-query -W -showformat ='$(Installed-Size) $(Package)/n' | sort -nr | less # dpkg-query -l | sort -nr | less # dpkg-query -s openoffice-de-en # apt-get remove openoffice-de-en knoppix@2[~]$ dpkg-query -s kmahjongg # aptitude purge openoffice-de-en kmahjongg # apt-get install abiword # deborphan | less # deborphan | xargs apt-get -y remove # apt-get clean # umount /proc # mkisofs -R -U -V "My Knoppix" -publisher "Ivan I. Ivanov" -hide-rr-moved -cache-inodes -no-bak -pad /media/hda1/knoppix/source/KNOPPIX | nice -5 /usr/bin/create_compressed_fs - 65536 > /media/hda1/knoppix/master/KNOPPIX/KNOPPIX # cd /media/hda1/knoppix/master # mkisofs -pad -l -r -J -v -V "MyKnop" -no-emul-boot -boot-load-size 4 -boot-info-table -b boot/isolinux/isolinux.bin -c boot/isolinux/boot.cat -hide-rr-moved -o /media/hda1/knoppix/knoppix.iso /media/hda1/knoppix/master # cdrecord -v -data knoppix.iso ----------------------------------------------------------------------------------------------------------------- OSSEC-HIDS. Установка и настройка Сергей Яремчук 31100 %3Cscript|%2Fscript|script>|script%3E|SRC=javascript|IMG%20| %20ONLOAD=|INPUT%20|iframe%20 XSS (Cross Site Scripting) attempt. attack, $ sudo apt-get install build-essentials $ wget –c http://www.ossec.net/files/ossec-hids-2.1.1.tar.gz $ wget –c http://www.ossec.net/files/ossec-hids-2.1.1_checksum.txt $ cat ossec-hids-2.1.1_checksum.txt $ md5sum ossec-hids-2.1.1.tar.gz $ sha1sum ossec-hids-2.1.1.tar.gz $ tar xzvf ossec-hids-2.1.1.tar.gz $ cd ossec-hids-2.1.1/ $ sudo ./install.sh $ sudo cat /var/ossec/logs/active-responses.log /var/ossec/bin/ossec-control start|stop 79200 /etc,/usr/bin, /usr/sbin /etc/hosts.deny // Запись в журнал 1 // Отправка почтового сообщения 7 host-deny local 6 600 $ sudo tail -f /var/ossec/logs/ossec.log $ sudo /var/ossec/bin/manage_agents $ sudo /var/ossec/bin/agent_control -i 001 $ sudo ./ossec-batch-manager.pl -a --ip 192.168.1.1 -n agent_1 -a --ip 192.168.1.2 -n agent_1 $ cat /var/ossec/logs/alerts/2009/Aug/ossec-alerts-28.log my $datepath=`date "+%Y/%b/ossec-alerts-%d.log"`; my $LOG='/var/ossec/logs/alerts/'. $datepath; $ sudo env LC_ALL=POSIX ./ossectop.pl $ sudo cat ossec-alerts-28.log | ./ossec_report_contrib.pl -s | mail root -s 'OSSEC summary report' 00 01 * * * (cat ossec-alerts-28.log | ./ossec_report_contrib.pl -s) $ wget –c http://www.ossec.net/files/ui/ossec-wui-0.3.tar.gz $ tar xzvf ossec-wui-0.3.tar.gz $ sudo mv ossec-wui-0.3 /var/www/ossec-wui $ /var/www/ossec-wui $ sudo chmod 770 /var/www/ossec-wui/tmp $ sudo chgrp www-data /var/www/ossec-wui/tmp $ sudo ./setup.sh $ sudo vi /etc/group $ cd src; make setmaxagents $ cd ..; sudo ./install.sh $ ulimit –a $ sudo ulimit –n 4096 $ sudo sysctl -w kern.maxfiles=4096 USER_BINARYINSTALL="x" ----------------------------------------------------------------------------------------------------------------- DBMS_SHEDULER. Запуск последовательных и зависимых заданий Антон Пищулин --Создание типа сообщения create or replace type dwh_que_type as object ( msg_id number, msg varchar2(50) ); --Создание таблицы DWH_QUE_TEST begin dbms_aqadm.create_queue_table( queue_table => 'DWH_QUE_TEST', queue_payload_type => 'DWH.DWH_QUE_TYPE', sort_list => 'ENQ_TIME', multiple_consumers => true, message_grouping => sys.dbms_aqadm.transactional); end; --Создание очереди DWH_QUE_TST begin dbms_aqadm.create_queue( queue_name => 'DWH_QUE_TST', queue_table => 'DWH_QUE_TEST', queue_type => sys.dbms_aqadm.normal_queue, max_retries => 500, retry_delay => 0, retention_time => 0); end; --Создание расписания TEST_SCH --(в Oracle EM Administration > Schedules) BEGIN dbms_scheduler.create_event_schedule( event_condition => 'tab.user_data.msg = ''TST_BEGIN''', queue_spec => '"DWH"."DWH_QUE_TST"', start_date => systimestamp at time zone 'Europe/Moscow', schedule_name => '"DWH"."TEST_SCH"'); END; --Создание пустой цепочки DWH_CH_TST --(в Oracle EM Administration > Chains) BEGIN sys.dbms_scheduler.create_chain( chain_name => '"DWH"."DWH_CH_TST"'); END; --Создания рабочих процедур create or replace procedure p1 is n number; BEGIN n:=0; --Здесь нужно вставить рабочий код. --Если возникает ошибка, то ее обязательно нужно --обработать и сгенерить новый exception exception when others then raise_application_error(-20112, 'p1'); END p1; create or replace procedure p2 is n number; BEGIN n:=0; --Здесь нужно вставить рабочий код. --Если возникает ошибка, то ее обязательно нужно --обработать и сгенерить новый exception exception when others then raise_application_error(-20112, 'p2'); END p2; create or replace procedure p3 is n number; BEGIN n:=0; --Здесь нужно вставить рабочий код. --Если возникает ошибка, то ее обязательно нужно --обработать и сгенерить новый exception exception when others then raise_application_error(-20112, 'p3'); END p3; --Создание программ (в Oracle EM Administration > Programs) BEGIN DBMS_SCHEDULER.CREATE_PROGRAM( program_name=>'"DWH"."pr1"', program_action=>'begin p1(); end;', program_type=>'PLSQL_BLOCK', number_of_arguments=>0, enabled=>TRUE); END; BEGIN DBMS_SCHEDULER.CREATE_PROGRAM( program_name=>'"DWH"."pr2"', program_action=>'begin p2(); end;', program_type=>'PLSQL_BLOCK', number_of_arguments=>0, enabled=>TRUE); END; --Последняя программа отличается от других BEGIN DBMS_SCHEDULER.CREATE_PROGRAM( program_name=>'"DWH"."pr3"', program_action=>' begin begin p3(); end; --Далее идет сервисная часть, посылающая клиенту --сообщение о завершении работы цепочки DECLARE enqueue_options DBMS_AQ.enqueue_options_t; dequeue_options DBMS_AQ.dequeue_options_t; message_properties DBMS_AQ.message_properties_t; message_handle RAW(16); message DWH_QUE_TYPE; BEGIN message := DWH_QUE_TYPE(1, ''TST_END''); DBMS_AQ.ENQUEUE( queue_name => ''DWH_QUE_TST'', enqueue_options => enqueue_options, message_properties => message_properties, payload => message, msgid => message_handle); COMMIT; END; end; ', program_type=>'PLSQL_BLOCK', number_of_arguments=>0, enabled=>TRUE); END; --Создание шагов цепочки BEGIN dbms_scheduler.define_chain_step( chain_name => '"DWH"."DWH_CH_TST"', step_name => '"S1"', program_name => '"DWH"."pr1"'); END; BEGIN dbms_scheduler.define_chain_step( chain_name => '"DWH"."DWH_CH_TST"', step_name => '"S2"', program_name => '"DWH"."pr2"'); END; BEGIN dbms_scheduler.define_chain_step( chain_name => '"DWH"."DWH_CH_TST"', step_name => '"S3"', program_name => '"DWH"."pr3"'); END; --Создание правил в цепочке BEGIN dbms_scheduler.define_chain_rule( chain_name => '"DWH"."DWH_CH_TST"', condition => 'true', rule_name => 'rule1', action => 'START "S1","S2"'); END; BEGIN dbms_scheduler.define_chain_rule( chain_name => '"DWH"."DWH_CH_TST"', condition => 'S1 COMPLETED AND S2 COMPLETED', rule_name => 'rule2', action => 'START "S3"'); END; BEGIN dbms_scheduler.define_chain_rule( chain_name => '"DWH"."DWH_CH_TST"', condition => 'S3 COMPLETED', rule_name => 'rule3', action => 'END'); END; --Активация цепочки BEGIN dbms_scheduler.enable('"DWH"."DWH_CH_TST"'); END; --Создание пакетной задачи --(в Oracle EM Administration > Jobs) BEGIN dbms_scheduler.create_job( job_name => '"DWH"."JOB_TST"', job_type => 'CHAIN', job_action => '"DWH"."DWH_CH_TST"', schedule_name => '"DWH"."TEST_SCH"', job_class => '"DEFAULT_JOB_CLASS"', auto_drop => FALSE, enabled => FALSE); dbms_scheduler.set_attribute( name => '"DWH"."JOB_TST"', attribute => 'logging_level', value => DBMS_SCHEDULER.LOGGING_FULL); dbms_scheduler.enable( '"DWH"."JOB_TST"' ); END; --Добавление пользователя dwh как подписчика очереди --сообщений(в Oracle EM Maintenance > Management > --Messaging) declare subscriber sys.aq$_agent; begin subscriber := sys.aq$_agent('"DWH"', '', 0); dbms_aqadm.add_subscriber( queue_name => '"DWH"."DWH_QUE_TST"', subscriber=> subscriber, rule=> '' , transformation=> ''); end; --Запуск очереди begin DBMS_AQADM.START_QUEUE( 'DWH_QUE_TST'); end; --Запуск цепочки DECLARE enqueue_options DBMS_AQ.enqueue_options_t; dequeue_options DBMS_AQ.dequeue_options_t; message_properties DBMS_AQ.message_properties_t; message_handle RAW(16); message DWH_QUE_TYPE; BEGIN message := DWH_QUE_TYPE(1, 'TST_BEGIN'); --Помещение в очередь сообщения TST_BEGIN DBMS_AQ.ENQUEUE( queue_name => 'DWH.DWH_QUE_TST', enqueue_options => enqueue_options, message_properties => message_properties, payload => message, msgid => message_handle); COMMIT; /*Ожидание сообщения о завершении работы цепочки*/ DECLARE enqueue_options DBMS_AQ.enqueue_options_t; dequeue_options DBMS_AQ.dequeue_options_t; message_properties DBMS_AQ.message_properties_t; message_handle RAW(16); message DWH_QUE_TYPE; s varchar(20); s2 varchar2(20); BEGIN s2 := 'TST_END'; s := ''''||s2||''''; dequeue_options.consumer_name := 'DWH'; dequeue_options.wait := DBMS_AQ.FOREVER; dequeue_options.navigation := DBMS_AQ.FIRST_MESSAGE; dequeue_options.deq_condition := ? 'tab.user_data.msg = '||s; --Читаем очередь, ожидаем сообщения TST_END DBMS_AQ.DEQUEUE( queue_name => 'DWH.DWH_QUE_TST', dequeue_options => dequeue_options, message_properties => message_properties, payload => message, msgid => message_handle); COMMIT; END; END; ----------------------------------------------------------------------------------------------------------------- Основные грани Ruby. От главных конструкций до приложения Дмитрий Васильев irb(main):001:0> (10 == 012) && (10 == 0xa) && (10 == 0b1010) irb(main):002:0> 12345678901234567890 / 4.5 irb(main):003:0> -33 == 33 irb(main):001:0> ("test" == 'test') && ("test" == %q/test/) irb(main):002:0> < "test\n" != 'test\n' irb(main):006:0> "#{10 * 10} times" irb(main):007:0> '#{10 * 10} times' irb(main):001:0> [1, 4.5, "test"] irb(main):002:0> [[1, 2], [3, 4]] irb(main):003:0> [[1, 2], [3, 4]][0] irb(main):004:0> [[1, 2], [3, 4]][-1] irb(main):001:0> {"one" => 1, 2 => "two"} irb(main):002:0> {"one" => 1, 2 => "two"}["one"] irb(main):003:0> {"one" => 1, 2 => "two"}[2] irb(main):004:0> {"one" => 1, 2 => "two"}["2"] irb(main):001:0> 1..10 irb(main):002:0> "a"..."z" irb(main):003:0> (1..10).to_a irb(main):004:0> ("a"..."f").to_a irb(main):001:0> PI = 3.1415 irb(main):002:0> PI = 3.1415 irb(main):003:0> $count = 0 irb(main):004:0> (1..10).each {|i| $count += i} irb(main):005:0> $count irb(main):001:0> (1..10).each do |i| irb(main):002:1* printf "#{i} " irb(main):003:1> end irb(main):001:0> n = 100 irb(main):002:0> if n == 100 then irb(main):003:1* "hundred" irb(main):004:1> elsif n == 10 then irb(main):005:1* "ten" irb(main):006:1> else irb(main):007:1* "one" irb(main):008:1> end irb(main):001:0> n = 100 irb(main):002:0> unless n == 100 then irb(main):003:1* "ten" irb(main):004:1> else irb(main):005:1* "hundred" irb(main):006:1> end irb(main):001:0> n = 100 irb(main):002:0> case n irb(main):003:1> when 1...10 then 1 irb(main):004:1> when 10...100 then 2 irb(main):005:1> when 100...1000 then 3 irb(main):006:1> end irb(main):001:0> while line = gets irb(main):002:1> printf "Line: #{line}" irb(main):003:1> end irb(main):001:0> i = 0 irb(main):002:0> until i > 5 irb(main):003:1> i += 1 irb(main):004:1> end irb(main):005:0> i irb(main):001:0> for i in [100, 10, 1] irb(main):002:1> printf "#{i} " irb(main):003:1> end class Shape def area() raise "Method not implemented" end end class Circle < Shape attr_reader :radius def initialize(radius) @radius = radius end def area() Math::PI * @radius end end class Square < Shape attr_reader :side def initialize(side) @side = side end def area() @side * @side end end irb(main):001:0> require "area" irb(main):002:0> s = Shape.new irb(main):003:0> s.area irb(main):004:0> c = Circle.new 10 irb(main):005:0> c.radius irb(main):006:0> c.radius = 20 irb(main):007:0> c.area irb(main):008:0> sq = Square.new 10 irb(main):009:0> sq.side irb(main):010:0> sq.area @shapes = { "circle" => Circle, "square" => Square } def area(line) parts = line.split raise "Wrong number of parameters" if parts.length < 2 shape = @shapes.fetch parts[0], nil raise "Unknown shape" if !shape arity = shape.allocate.method(:initialize).arity sizes = parts[1..-1].map {|i| i.to_f} raise "Wrong number of arguments" if arity != sizes.length shape.new(*sizes).area end def main() begin print "> " begin break if !line = gets puts area line rescue Interrupt break rescue RuntimeError => why print "?#{why}\n" end end while true end main $ ruby area.rb > circle 1 > circle 40.3 > square 20 > unknown 30 ----------------------------------------------------------------------------------------------------------------- Язык Python. Дополнительные типы коллекций Сергей Супрунов >>> import collections >>> User = collections.namedtuple('User', 'name phone login speed') >>> vasya = User('Петров В. И.', 22343, 'vasya', 128) >>> for field in vasya: ... print(field) # поведение аналогично кортежу >>> print(vasya[3]) # работает как обычный кортеж >>> print(vasya.login, vasya.speed) >>> tvasya = tuple(vasya) # если нужен простой кортеж >>> tvasya >>> Bool = collections.namedtuple('Bool', 'False True', rename=True) >>> test = Bool('2 > 3', '7 < 8') >>> test NAME, PHONE, LOGIN, SPEED = (0, 1, 2, 3) # или range(4) vasya = ('Петров В. И.', 22343, 'vasya', 128) print(vasya[LOGIN]) >>> counter = {} >>> sample = [1,2,1,4,2,3,4] >>> for dig in sample: ... counter[dig] += 1 ... # Первый способ if dig in counter: counter[dig] += 1 else: counter[dig] = 1 # Второй способ counter[dig] = counter.get(dig, 0) + 1 # Третий способ counter[dig] = counter.setdefault(dig, 0) + 1 # Четвёртый способ try: counter[dig] += 1 except KeyError: counter[dig] = 1 counter = collections.defaultdict(int) for dig in sample: counter[dig] += 1 >>> fifo = collections.deque() >>> stack = collections.deque() >>> fifo.appendleft(1) >>> fifo.appendleft(2) >>> fifo.appendleft(3) >>> fifo.pop() >>> fifo.pop() >>> stack.append(1) >>> stack.append(2) >>> stack.append(3) >>> stack.pop() >>> stack.pop() #!/usr/local/bin/python3.1 import collections, random baraban = collections.deque((1,0,0,0,0,0)) baraban.rotate(random.randint(5,99)) for shot in range(len(baraban)): input('Чья очередь - нажмите Enter... ') if baraban[shot]: print('БА-БАХ!!!') break else: print('клац') print('Финита ля комедия, господа!') >>> od = c.OrderedDict() >>> od['w'] = 123 >>> od['a'] = 34 >>> od.keys() >>> sample = [1,2,1,4,2,3,4] >>> cnt = collections.Counter(sample) >>> cnt >>> cnt[4] >>> text = open('/home/amsand/reconf.py').read() >>> cnt = c.Counter(text) >>> cnt.most_common(3) >>> a = [1,2,3] >>> b = a >>> b[2] = 5 >>> a >>> b >>> a is b -----------------------------------------------------------------------------------------------------------------