Эмуляторы Android. Общий обзор. BlueStacks Рашид Ачилов $ su # cd /data/system # rm -f accounts.db ----------------------------------------------------------------------------------------------------------------- SUSE Cloud 1.0. Обзор возможностей системы для создания облака Сергей Яремчук # screen /opt/dell/bin/install-chef-suse.sh ----------------------------------------------------------------------------------------------------------------- Электронная почта и дисковые квоты. Можно ли создать собственную систему квот? Александр Белоусов Листинг 1. Сценарий mail.quota с пронумерованными строками #!/bin/sh cd /usr/local/libexec/quota/ #Создание цикла, в котором переменной mbox последовательно присваиваются имена почтовых ящиков пользователей #и с ними последовательно выполняются действия, указанные между операторами do и done for mbox in /var/spool/mail/* do #Переменная mbox включает полный путь к почтовому ящику. Выделяем из него только имя файла и присваиваем его переменной user user=`basename ${mbox}` #Вычисляем размер почтового ящика в мегабайтах mboxsize=`du -sm "${mbox}" | cut -f1` #Обновляем счетчик почтовых ящиков num=$(( ${num} + 1 )) #Если пользователь уже был заблокирован, присваиваем его имя переменной block. #Комментарий в БД access «Unfortunately the limit of disk space for the user» #специально сделан уникальным и добавляется туда при блокировке пользователя, как будет показано ниже block=`grep -m1 "To:${user}@" /etc/mail/access | grep 'Unfortunately the limit of disk space for the user' | cut -d: -f2 | cut -d@ -f1` #Проверяем, не превысил ли размер почтового ящика «мягкий» лимит в 800 мегабайт if [ ${mboxsize} -lt 800 ] then #Формируем сообщения для администратора о том, что пользователь не превысил «мягкий» лимит echo "${num} ${user} ${mboxsize} не превысил 800М" #Делаем вложенную проверку – был ли ранее заблокирован данный пользователь, освободивший теперь место на диске if [ "${user}" = "${block}" ] then #Формируем сообщения для администратора о том, что ранее заблокированный пользователь, освободивший теперь место на диске, разблокируется echo " ${num} ${user} был заблокирован. Будем разблокировать" #Удаляем строку, блокирующую данного пользователя, из файла /etc/mail/access, который используется как исходный для формирования базы данных. #Практически /etc/mail/access – это текстовый файл со специальным синтаксисом sed -i /To:${user}@/d /etc/mail/access #Генерируем БД access из исходника makemap hash /etc/mail/access.db < /etc/mail/access #Отправляем сообщение пользователю о том, что его почтовый ящик разблокирован. Файл quota.off содержит текст письма. #Его пример будет показан ниже (см. листинг 2) /usr/bin/mutt -s "Внимание, Ваш почтовый ящик разблокирован!" "${user}@localhost" < ./quota.off fi #Проверяем, не превысил ли размер почтового ящика пользователя «жесткий» лимит в 1000 мегабайт elif [ ${mboxsize} -gt 1000 ] then #Если это так, формируем сообщения для администратора о том, что пользователь превысил «жесткий» лимит echo "${num} ${user} ${mboxsize} превысил 1000М" #Делаем вложенную проверку – был ли ранее заблокирован данный пользователь if [ "${user}" = "${block}" ] then #Формируем сообщения для администратора о том, что этот пользователь был ранее заблокирован и остается заблокированным echo "${num} ${user} был заблокирован. Оставляем заблокированным". #Если же данный пользователь ранее не был заблокирован, то для блокировки добавляем строку с его именем, кодом #ошибки для SMTP-серверов отправителей и комментарием в файл /etc/mail/access. Делаем код ошибки не фатальным, #а временным, чтобы пользователь мог получить свою почту, если удалит свою почту на сервере в течение пяти дней. #Пять дней – это стандартное время хранения почты в очереди при возникновении временной ошибки доставки else echo "To:${user}@ ERROR:4.2.2:\"450 mailbox full\" # Unfortunately the limit of disk space for the user's mailbox is exceeded.\ New mail will not be accepted temporarily.\ Please,\ report about it to Your recipient through alternative channels of communication" >> /etc/mail/access #До осуществления блокировки отправляем последнее письмо пользователю о том, что он заблокирован. #Пример содержания текста письма, которое вставляется из файла quota.on, будет показан ниже (см. листинг 3) /usr/bin/mutt -s "Внимание, размер Вашего почтового ящика превысил допустимый лимит!" "${user}@localhost" < ./quota.on #Генерируем БД access из исходника makemap hash /etc/mail/access.db < /etc/mail/access fi #Начало блока действий при условии, что пользователь превысил «мягкий» лимит, но не превысил «жесткий» лимит else #Формируем сообщения для администратора об этом echo "${num} ${user} ${mboxsize} превысил 800М, но не превысил 1000М" #Делаем вложенную проверку – был ли ранее заблокирован данный пользователь if [ "${user}" = "${block}" ] then #Если да, то формируем сообщения для администратора о том, что этот пользователь был ранее заблокирован иразблокируется echo "${num} ${user} был заблокирован. Разблокируем". #Удаляем строку, блокирующую данного пользователя, #из файла /etc/mail/access sed -i /To:${user}@/d /etc/mail/access #Генерируем БД access из исходника makemap hash /etc/mail/access.db < /etc/mail/access #Отправляем сообщение пользователю о том, что его почтовый ящик разблокирован. В тему письма вставляем его размер /usr/bin/mutt -s "Внимание, Ваш почтовый ящик разблокирован! Его размер ${mboxsize} Мб." "${user}@localhost" < ./quota.off #Если же данный пользователь не был заблокирован, то формируем сообщения для администратора об этом else echo "${user} не был заблокирован. Пока..." #И отправляем сообщение пользователю о том, что размер почтового ящика имеет ограничение. #Пример содержания текста письма, которое вставляется из файла quota.warning, будет показан ниже (см. листинг 4) /usr/bin/mutt -s "Внимание, размер почтового ящика имеет ограничение!" "${user}@localhost" < ./quota.warning fi fi done #Завершающий блок сценария нужен на тот случай, когда аккаунт заблокированного пользователя удалили из системы. #Эта ситуация возможна, если администратор обнаружил, что пользователь годами не проверяет свой почтовый ящик #и удаляет его. При этом в базе данных access запись остается. Устраняем этот недостаток #В цикле считываем строки исходного файла БД access, содержащие имена заблокированных пользователей cat /etc/mail/access | grep 'Unfortunately the limit of disk space for the user' | while read i do #Из всего текста строки выделяем имя пользователя и присваиваем его значение переменной user user=`echo "${i}" | cut -d: -f2 | cut -d@ -f1` #Формируем для администратора список заблокированных пользователей echo "юзер ${user} в базе" #Если почтовый ящик заблокированного пользователя существует if [ -f /var/spool/mail/${user} ] then #Формируем для администратора сообщение, что данный заблокированный пользователь существует echo "юзер ${user} существует" #Если почтовый ящик заблокированного пользователя не существует else #Формируем для администратора сообщение, что данный заблокированный пользователь не существует echo "юзер ${user} был заблокирован, но не существует. Удаляем из access.db" #Удаляем строку, блокирующую данного пользователя, из файла /etc/mail/access sed -i /To:${user}@/d /etc/mail/access #Генерируем БД access из исходника makemap hash /etc/mail/access.db < /etc/mail/access #Отправляем сообщение пост-мастеру о том, что пользователь был заблокирован на момент удаления его аккаунта и запись #об этом из access.db удалена grep -v Unfortunately | /usr/bin/mutt -s "Внимание, юзер ${user} был заблокирован на момент удаления его аккаунта. Удаляем запись из access.db" "postmaster@localhost" fi done exit 0 Листинг 2. Пример сообщения пользователю о том, что его почтовый ящик разблокирован. Файл quota.off Внимание! Прием почты в Ваш адрес восстановлен. Он был заблокирован ранее из-за превышения лимита доступного дискового пространства для Вашего почтового ящика на сервере example.ru. Благодарю за принятые меры по освобождению дискового пространства сервера. С уважением, администратор электронной почты Листинг 3. Пример сообщения пользователю о том, что его почтовый ящик превысил «жесткий» лимит. Файл quota.on Внимание! Уведомляю Вас, что размер Вашего почтового ящика на сервере example.ru превысил предельно допустимый: 1 Гигабайт. В связи с этим почта в Ваш адрес временно не принимается! Срочно примите меры по освобождению дискового пространства сервера, занятого Вашей почтой. Отправители адресованной Вам почты получают уведомление, что Ваш почтовый ящик превысил лимит доступного для него дискового пространства. Возможной причиной переполнения Вашего почтового ящика на сервере является настройка Вашего почтового клиента. Если Ваша почтовая программа настроена так, чтобы принятые письма на сервере не удалялись после приема, измените эту настройку. Прием почты будет восстановлен автоматически после того, как Вы примите указанные меры. Прошу отнестись к этому с пониманием, дисковое пространство сервера ограничено. С уважением, администратор электронной почты Листинг 4. Пример сообщения пользователю о том, что его почтовый ящик превысил «мягкий» лимит. Файл quota.warning Здравствуйте! Уведомляю Вас, что размер Вашего почтового ящика на сервере example.ru приближается к предельно допустимому: 1 Гигабайт. Срочно примите меры по освобождению дискового пространства сервера, занятого Вашей почтой. В противном случае после превышения этого лимита почта в Ваш адрес приниматься перестанет до тех пор, пока данные меры Вами не будут приняты. Возможной причиной переполнения Вашего почтового ящика на сервере является настройка Вашего почтового клиента. Если Ваша почтовая программа настроена так, чтобы принятые письма на сервере не удалялись после приема, измените эту настройку. Прошу отнестись к этому с пониманием, дисковое пространство сервера ограничено. С уважением, администратор электронной почты Листинг 5. Пример файла конфигурации сrontab для выполнения по расписанию сценария mail.quota # Запуск скрипта, проверяющего квоты пользователей LANG="ru_RU.UTF-8" 10 2 * * * root /usr/local/libexec/quota/mail.quota ----------------------------------------------------------------------------------------------------------------- Корпоративный сервер мгновенных сообщений Дмитрий Андриенко $ sudo apt-get install ejabberd override_local %% Admin user {acl, admin, {user, "ADMIN", "SERVER_NAME"}} %% Hostname {hosts, ["SERVER_NAME"] {hosts, ["example.org"] %%% ACCESS RULES --------------------------------------------- {access, register, [{allow, all}]} {language, "ru"} $ sudo ejabberdctl register ADMIN SERVER_NAME PASSWORD $ sudo /etc/init.d/ejabberd restart >psi-win-setup.exe /S [ /D:c:\stuff\psi\ ] start /wait \\srv4-dc\install_GPO\PSI\psi-0.14-win-setup.exe /S ----------------------------------------------------------------------------------------------------------------- Управление Linux-системами с помощью Fabric Сергей Яремчук $ sudo apt-get -y install fabric $ sudo apt-get -y install python-pip $ sudo pip install fabric $ fab -H system1,system2 -- uname -a $ fab -H system1,admin@example.org -- uptime user = admin fabfile = fabtasks.py env.user = 'user' env.password = 'p@SsW0rd' env.parallel = 'True' def task(...): with settings(warn_only=True): какой то код @with_settings(warn_only=True) def hello(name="world"): print("Hello %s!" % name) $ fab hello $ fab hello:name=Linux $ fab hello hello:Linux hello:BSD from fabric.api import * from fabric.api import settings, run, env env.hosts = ['host1', 'host2','host3'] def task1(): run('uname -a') def task2(): run('df -h') $ fab task1 task2 -x host2 @hosts('host1','user2@host2') my_hosts = ('host1', 'host2') @hosts(my_hosts) def funk(): env.hosts = ['host1', 'host2'] env.roledefs = { 'web': ['www1', 'www2'], 'mail': ['smtp', 'pop3'] } env.roledefs = { 'web': ['www1', 'www2'], 'mail': ['smtp', 'pop3'] } ip = prompt('Please enter host IP', default='127.0.0.1' validate=r'((25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(25[0-5]|2[0-4]\d|[01]?\d\d?)') from fabric.api import * env.hosts = ['host1', 'host2'] env.user = 'user_name' # обновляем систему и ставим Apache def install_apache(): sudo('apt-get update && apt-get dist-upgrade') sudo('apt-get -y install apache2') # упаковываем каталог /var/www/ def pack(): local('tar czf /tmp/www.tgz /var/www/', capture=False) # переносим архив на удаленную систему def deploy(): pack() put('/tmp/www.tgz', '/tmp/') with cd('/var/www/'): run('tar xzf /tmp/www.tgz') $ fab install_apache deploy $ fab --list ----------------------------------------------------------------------------------------------------------------- Автоматические группы безопасности. Часть 1. Иерархическое зеркало реляционных данных Вадим Андросов Листинг 1. Создание атрибута «Дата рождения» dn: CN=birthDate,CN=Schema,CN=Configuration,DC=X changetype: ntdsschemaadd objectClass: top objectClass: attributeSchema cn: birthDate lDAPDisplayName: birthDate adminDisplayName: birthDate attributeID: 1.2.840.113556.1.8000.2554.2.1 attributeSyntax: 2.5.5.11 oMSyntax: 24 searchFlags: 1 isSingleValued: TRUE systemOnly: FALSE adminDescription: Birth date CN=Schema,CN=Configuration,DC=prumpum,DC=ua <<имя свойства>><<двоеточие>><<значение>> Листинг 2. Создание атрибута «Следующая дата рождения» dn: CN=nextBirthDate,CN=Schema,CN=Configuration,DC=X …… cn: nextBirthDate lDAPDisplayName: nextBirthDate adminDisplayName: nextBirthDate attributeID: 1.2.840.113556.1.8000.2554.2.2 …… Листинг 3. Создание атрибута «Возраст» dn: CN=age,CN=Schema,CN=Configuration,DC=X changetype: ntdsschemaadd objectClass: top objectClass: attributeSchema cn: age lDAPDisplayName: age adminDisplayName: age attributeID: 1.2.840.113556.1.8000.2554.2.3 attributeSyntax: 2.5.5.9 oMSyntax: 2 searchFlags: 1 isSingleValued: TRUE systemOnly: FALSE adminDescription: age Листинг 4. Создание атрибута «Должность» dn: CN=position,CN=Schema,CN=Configuration,DC=X changetype: ntdsschemaadd objectClass: top objectClass: attributeSchema cn: position lDAPDisplayName: position adminDisplayName: position attributeID: 1.2.840.113556.1.8000.2554.2.4 attributeSyntax: 2.5.5.12 oMSyntax: 64 searchFlags: 1 isSingleValued: TRUE systemOnly: FALSE adminDescription: Position Листинг 5. Обновление кэша схемы dn: changetype: ntdsschemamodify add: schemaUpdateNow schemaUpdateNow: 1 - Листинг 6. Расширение для класса user dn: CN=userExtension,CN=Schema,CN=Configuration,DC=X changetype: ntdsschemaadd objectClass: top objectClass: classSchema cn: userExtension name: userExtension adminDisplayName: userExtension lDAPDisplayName: userExtension governsID: 1.2.840.113556.1.8000.2554.1.1 mayContain: birthDate mayContain: nextBirthDate mayContain: position mayContain: age objectClassCategory: 3 systemOnly: FALSE adminDescription: user class extension Листинг 7. Модификация системного класса user dn: CN=User,CN=Schema,CN=Configuration,DC=X changetype: ntdsschemamodify add: auxiliaryClass auxiliaryClass: userExtension - Листинг 8. Создание однозначной ссылки teamLeader dn: CN=teamLeader,CN=Schema,CN=Configuration,DC=X changetype: ntdsschemaadd objectClass: top objectClass: attributeSchema cn: teamLeader adminDisplayName: teamLeader lDAPDisplayName: teamLeader attributeID: 1.2.840.113556.1.8000.2554.2.5 LinkID: 1.2.840.113556.1.2.50 attributeSyntax: 2.5.5.1 oMSyntax: 127 isSingleValued: TRUE searchFlags: 1 systemOnly: FALSE adminDescription: Team leader forward reference Листинг 9. Создание многозначной ссылки teamMembers dn: CN=teamMembers,CN=Schema,CN=Configuration,DC=X ……… cn: teamMembers adminDisplayName: teamMembers lDAPDisplayName: teamMembers attributeID: 1.2.840.113556.1.8000.2554.2.6 isSingleValued: FALSE ……… Листинг 10. Обратная ссылка dn: CN= leadsTeams,CN=Schema,CN=Configuration,DC=X changetype: ntdsschemaadd objectClass: top objectClass: attributeSchema cn: leadsTeams adminDisplayName: leadsTeams lDAPDisplayName: leadsTeams attributeID: 1.2.840.113556.1.8000.2554.2.7 LinkID: 1.2.840.113556.1.8000.2554.2.5 attributeSyntax: 2.5.5.1 oMSyntax: 127 isSingleValued: FALSE searchFlags: 1 systemOnly: FALSE adminDescription: Team leader backward reference Листинг 11. Добавление обратных ссылок в класс пользователя dn: CN=User,CN=Schema,CN=Configuration,DC=X changetype: ntdsschemamodify add: mayContain mayContain: leadsTeams - add: mayContain mayContain: memberOfTeams - Листинг 12. Создание класса team dn: CN=team,CN=Schema,CN=Configuration,DC=X changetype: ntdsschemaadd objectClass: top objectClass: classSchema cn: team adminDisplayName: team name: team lDAPDisplayName: team rDnAttID: cn governsID: 1.2.840.113556.1.8000.2554.1.2 possSuperiors: organizationalUnit mayContain: teamLeader mayContain: teamMembers objectClassCategory: 1 systemOnly: FALSE adminDescription: Team class ldifde -i -f schExt.ldif -c "DC=X" "DC=prumpum,DC=ua" regsvr32 schmmgmt.dll prumpum.ua/ou1/ou2/object1 CN=object,OU=ou2,OU=ou1,DC=prumpum,DC=ua ----------------------------------------------------------------------------------------------------------------- Атаки типа MAC flooding. Насколько они страшны? Юрий Денисов switchport port-security violation shutdown switchport port-security maximum 5 ----------------------------------------------------------------------------------------------------------------- «1С» на Oracle. Как превратить миф в реальность Олег Филиппов lsnrctl start sqlplus / as sysdba startup; quit; lsnrctl status sqlplus/as sysdba alter database mount; alter database open shutdown immediate export ORACLE_BASE=/u01/app/oracle export ORACLE_SID=dbname export ORACLE_OWNER=oracle export ORACLE_HOME=/u01/app/oracle/product/11.2.0/dbhome_1 export ORACLE_UNQNAME=dbname export ORACLE_HOSTNAME=hostname export NLS_LANG=RUSSIAN_CIS.AL32UTF8 #!/bin/sh export ORACLE_OWNER=oracle export ORACLE_HOME=/u01/app/oracle/product/11.2.0/dbhome_1 export ORACLE_SID=dbname export ORACLE_BASE=/u01/app/oracle export ORACLE_UNQNAME=dbname export ORACLE_HOSTNAME=hostname export PATH=$ORACLE_HOME:$PATH export PATH=$ORACLE_HOME/bin:$PATH su oracle -c "$ORACLE_HOME/bin/lsnrctl start" su oracle -c "$ORACLE_HOME/bin/dbstart" su oracle -c "$ORACLE_HOME/bin/sqlplus / as sysdba @/home/oracle/startup.sql" su oracle -c "$ORACLE_HOME/bin/emctl start dbconsole" alter system set parameter=value scope=spfile impdp SYSTEM/password FILE=File.dmp FROMUSER=SourceSchema TOUSER=DestSchema TABLE_EXISTS_ACTION=REPLACE expdp SYSTEM/password schemas=schema directory=data_pump_dir file="File.dmp" ----------------------------------------------------------------------------------------------------------------- Задача сравнения списков, или Еще раз про XML Сергей Ильичев Листинг 1. Структура xml-файла для хранения списка Ключ Параметр1 Параметр2 ... ... ... ... Листинг 2. Макрос для выгрузки столбцов Excel в xml-файл Sub Save2XML() ' ' Save2XML Макрос ' 'открываем файл для записи Open "c:\data.xml" For Append As #1 Dim cur_range As Range With ActiveSheet Set cur_range = Selection cur_range.Activate Print #1, " " For x = 1 To cur_range.Rows.Count Print #1, "" 'берем значения только первых выделенных трех полей Print #1, ""+cur_range(x, 1).Text+"" + "" + cur_range(x, 2).Text + "" + "" + cur_range(x, 3).Text + "" Print #1, "" Next x Print #1, "" End With 'закрываем файл Close #1 End Sub Листинг 3. Файл Record.java package si.xml.castor.comparator; public class Record { private String key; private String value1; private String value2; public Record() {}; public Record(String key, String value1, String value2) { this.key = key; this.value1 = value1; this.value2 = value2; } public void setKey(String key) { this.key = key; } public String getKey() { return key; } public void setValue1(String value1) { this.value1 = value1; } public String getValue1() { return value1; } public void setValue2(String value2) { this.value2 = value2; } public String getValue2() { return value2; } } Листинг 4. Файл RecordsList.java package si.xml.castor.comparator; import java.util.ArrayList; public class RecordsList { private ArrayList records; public RecordsList() {}; public RecordsList(Record record) { this.records = new ArrayList(); records.add(record); } public void setRecords(ArrayList records) { this.records = records; } public ArrayList getRecords() { return records; } public void addRecord(Record record) { records.add(record); } public void deleteRecord(int index) { records.remove(index); } } Листинг 5. Файл ListMapUnmarshaller.java package si.xml.castor.comparator; import java.io.FileReader; import java.util.Iterator; import java.util.ArrayList; import org.exolab.castor.xml.Unmarshaller; import org.exolab.castor.mapping.Mapping; public class ListMapUnmarshaller { private RecordsList lst; ListMapUnmarshaller() {}; public RecordsList readFile( String xml_file) { Mapping mapping = new Mapping(); try { mapping.loadMapping("list-map.xml"); FileReader reader = new FileReader(xml_file); Unmarshaller unm = new Unmarshaller(RecordsList.class); unm.setMapping(mapping); lst = (RecordsList)unm.unmarshal(reader); } catch (Exception e) { System.err.println(e.getMessage()); e.printStackTrace(System.err); } return lst; } } Unmarshaller unm = new Unmarshaller(RecordsList.class); unm.setMapping(mapping); lst = (RecordsList)unm.unmarshal(reader); mapping.loadMapping("list-map.xml"); Листинг 6. Файл list-map.xml Листинг 7. Программа сравнения двух списков – файл c3f.java package si.xml.castor.comparator; import java.io.*; import java.util.Iterator; import java.util.*; public class c3f { private RecordsList rlst; private RecordsList rlst2; static Comparator keyorder = new Comparator() { public int compare(Record o1, Record o2) { return o1.getKey().compareTo(o2.getKey()); } }; private ArrayList sortByKey(ArrayList lst){ Collections.sort(lst, keyorder); return lst; } c3f() {}; c3f(String xml_file_1, String xml_file_2) { rlst = new ListMapUnmarshaller().readFile(xml_file_1); rlst2 = new ListMapUnmarshaller().readFile(xml_file_2); } private int compareTwoLists() { //возвращает 1 – если есть ошибки, 0 – если ошибок нет ArrayList records = rlst.getRecords(); ArrayList records2 = rlst2.getRecords(); TreeMap erTM = new TreeMap(); //счетчик ошибок int ern = 0; //сортируем списки records = sortByKey(records); records2 = sortByKey(records2); //проверяем первый список на двойные значения ключа String keyPrev = "", keyNext; erTM.put( ern, "Проверяем 1-й список" ); for ( Iterator i = records.iterator(); i.hasNext(); ) { Record record = (Record)i.next(); keyNext = record.getKey(); //если есть двойные значения ключа в первом списке – ошибка if (keyNext.equals(keyPrev)) { ern++; erTM.put( ern, record.getKey() +" - двойное значение ключа в первом списке"); } keyPrev = keyNext; } //первый список проверяем на наличие ключей во втором списке и равенство Параметра1 и Параметра2 вспомогательная переменная boolean eq1; for ( Iterator r = records.iterator(); r.hasNext(); ) { eq1 = false; Record record = (Record)r.next(); for ( Iterator k = records2.iterator(); k.hasNext(); ) { Record record2 = (Record)k.next(); if ( record2.getKey().equals( record.getKey() ) ) { eq1 = true; if ( !record2.getValue1().equals( record.getValue1() ) ) { ern++; erTM.put ( ern, record.getKey() + " (" + record.getValue1() + ", " + record.getValue2() + ") - для одного ключа отличие первого Параметра во втором списке"); } if ( !record2.getValue2().equals( record.getValue2() ) ) { ern++; erTM.put ( ern, record.getKey() + " (" + record.getValue1() + ", " + record.getValue2() + ") - для одного ключа отличие второго Параметра во втором списке"); } } } if ( !eq1 ) { ern++; erTM.put( ern, record.getKey() + " - ключ есть в первом и его нет во втором списке" ); } } //проверяем второй список на двойные значения ключа код аналогичен приведенному выше для первого списка ... //второй список проверяем на наличие ключей в первом списке код аналогичен приведенному выше для первого списка ... //если есть ошибки – сохраняем в файл if (ern > 1) { saveErrors2file( erTM ); return 1; } else return 0; } public void saveErrors2file(TreeMap err_map) { try { PrintWriter out = new PrintWriter(new FileWriter("errors.log")); Set entries = err_map.entrySet(); for (Map.Entry entry : entries) { out.println( entry.getValue() ); } out.close(); } catch (IOException exc) {} } public static void main (String[] args) { if( args.length > 0 ) { if ( args.length == 2 ) { c3f lf = new c3f ( args[0], args[1] ); if ( lf.compareTwoLists() == 1 ) { System.out.println↵ ("There are errors!See errors.log file"); } else { System.out.println("Lists are equals!"); } } } else { System.out.println("must to have two parameters!"); System.exit(0); } } } Листинг 8. Файл .profile export CASTOR_HOME=/usr/local/java/castor-1.3 export CASTOR_CLASSES= $CASTOR_HOME/castor-1.3.jar: $CASTOR_HOME/castor-1.3-xml.jar: $CASTOR_HOME/lib/commons-logging-1.1.jar: $CASTOR_HOME/castor-1.3-core.jar export CLASSPATH=$CASTOR_CLASSES:. javac –d . *.java java si.xml.castor.comparator.c3f file1.xml file2.xml Листинг 9. Файл start.bat java -cp .; c:\serg\castor-1.3\castor-1.3.jar; c:\serg\castor-1.3\castor-1.3-xml.jar; c:\serg\castor-1.3\lib\commons-logging-1.1.jar; c:\serg\castor-1.3\castor-1.3-core.jar si.xml.castor.comparator.c3f file1.xml file2.xml notepad.exe errors.log ----------------------------------------------------------------------------------------------------------------- Варианты реализации паттерна Singleton Александр Майоров class MySingleton { private function __construct(){} private function __clone(){} protected static $Instance; final public static function Instance(){ if (!is_object(self::$Instance)) { self::$Instance = new self(); } return self::$Instance; } } abstract class Singleton { private function __construct(){} private function __clone(){} protected static $Instance; final public static function Instance(){ if (is_null(self::$Instance)) { self::$Instance = new self(); } return self::$Instance; } } class MySingleton1 extends Singleton { public $foo = 1; } $Obj1 = MySingleton1::Instance(); class Singleton { private function __construct(){} private function __clone(){} protected static $Instance; final public static function Instance(){ if (is_null(self::$Instance)) { self::$Instance = new self(); } return self::$Instance; } } class MySingleton1 extends Singleton { public $foo = 1; } $Obj1 = MySingleton1::Instance(); var_dump($Obj1); abstract class Singleton { private function __construct(){} private function __clone(){} protected static $Instance; final public static function Instance(){ if (empty(static::$Instance)) { static::$Instance = new static(); } return static::$Instance; } } class MySingleton1 extends Singleton { public $foo = 1; } class MySingleton2 extends Singleton { public $foo = 2; } $Obj1 = MySingleton1::Instance(); $Obj2 = MySingleton2::Instance(); var_dump($Obj1, $Obj2); class MySingleton1 extends Singleton { protected static $Instance; public $foo = 1; } class MySingleton2 extends Singleton { protected static $Instance; public $foo = 2; } abstract class Singleton { private function __construct(){} private function __clone(){} private static $Instance = array(); final public static function Instance(){ $calledClass = get_called_class(); if (isset(self::$Instance[$calledClass])) { self::$Instance[$calledClass] = new static(); } return self::$Instance[$calledClass]; } } class MySingleton1 extends Singleton { public $foo = 1; } class MySingleton2 extends Singleton { public $foo = 2; } abstract class Singleton { final public static function Instance(){ $class = get_called_class(); if (!static::$Instance) { static::$Instance = new $class; } return static::$Instance; } protected function __construct(){} protected function __clone() {} } abstract class Singleton { final public static function Instance(){ $class = get_called_class(); if (!$class::$Instance) $class::$Instance = new $class; return $class::$Instance; } protected function __construct(){} protected function __clone() {} } trait Singleton { private function __construct(){} private function __clone(){} private static $Instance; final public static function Instance(){ if (empty(static::$Instance)) { static::$Instance = new static(); } return static::$Instance; } } class MySingleton1 { use Singleton; public $foo = 1; } class MySingleton2 { use Singleton; public $foo = 2; } final public static function Instance(){ static::$Instance or static::$Instance = new static; return static::$Instance; } function MyClass() { return MyClass::Instance(); } abstract class Singleton { private function __construct(){} private function __clone(){} final public static function Instance(){ static $instance; $instance or $instance = new static; return $instance; } } ----------------------------------------------------------------------------------------------------------------- PHP-интерпретатор. Тонкая настройка параметров в режиме FastCGI Павел Одинцов #!/bin/bash export PHP_FCGI_MAX_REQUESTS=5000 export PHP_FCGI_CHILDREN=5 php-cgi -b localhost:9999 , PHP_FCGI_CHILDREN=1 PHP_FCGI_MAX_REQUESTS=5 php-cgi -b localhost:9999 while true ; do php -f test.php |grep '#ok#' > /dev/null; if [ $? != 0 ]; then echo "Request failed"; fi ; done ----------------------------------------------------------------------------------------------------------------- Компьютерная графика на основе OpenGL. Часть 1. Каркас приложения OpenGL в среде разработки Delphi VCL Алексей Верижников procedure TForm1.FormCreate(Sender: TObject); begin h_DC := GetDC(Form1.Handle); SetOpenGL(H_DC,H_RC); glInit; end; procedure TForm1.glInit; begin // Black Background glClearColor(0.0, 0.0, 0.0, 0.0); // Enables Smooth Color Shading glShadeModel(GL_SMOOTH); // Depth Buffer Setup glClearDepth(1.0); // Enable Depth Buffer glEnable(GL_DEPTH_TEST); // The Type Of Depth Test To Do glDepthFunc(GL_LESS); ... glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); glEnable(GL_CULL_FACE); glCullFace(GL_BACK); ... glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); ... end; //Включение z-буффера glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LESS); glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); procedure TForm1.FormResize(Sender: TObject); begin if (Form1.Height = 0) then Form1.Height := 1; glViewport(0, 0, Width, Height); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(45.0, Width/Height, 1.0, 100.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); end; gluPerspective(45.0, Width/Height, 1.0, 100.0);. procedure TForm1.glDraw; begin glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT); glLoadIdentity; glTranslatef(0.0, -0.05, -4.5); glRotatef(ScrollBar1.Position,1,0,0); glRotatef(ScrollBar2.Position,0,1,0); glRotatef(angle,1,1,1); col[0]:=0.0; col[1]:=1.0; col[2]:=0.0; col[3]:=0.0; glMaterialfv(GL_FRONT,GL_SPECULAR,PGLFloat(col)); glutSolidCube(1.333); col[0]:=0.0; col[1]:=0.0; col[2]:=1.0; col[3]:=0.0; glMaterialfv(GL_FRONT,GL_SPECULAR,PGLFloat(col)); glutSolidSphere(1,26,26); end; procedure TForm1.FormPaint(Sender: TObject); begin glDraw; SwapBuffers(h_DC); end; “растянуть(3)” “сместить (2)” “повернуть(1)” procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction); begin dispose(col); H_WND:=Form1.Handle; DestroyOpenGL(H_WND,H_DC,H_RC); end; ----------------------------------------------------------------------------------------------------------------- Facebook под микроскопом. Часть 1 Игорь Савчук $ wget http://www.us.apache.org/dist/hadoop/common/hadoop-1.1.0/hadoop-1.1.0.tar.gz $ tar xfz hadoop-1.1.0.tar.gz $ cd hadoop-1.1.0/ export JAVA_HOME=/System/Library/Frameworks/JavaVM.framework/Versions/1.6.0/Home export HADOOP_INSTALL=/home/savgor/hadoop-1.1.0 export PATH=$PATH:$HADOOP_INSTALL/bin $ hadoop version export LDFLAGS="-L/usr/local/cdh/hadoop/c++/lib -L/usr/java/default/jre/lib/amd64/server" export CPPFLAGS="-I/usr/java/default/include -I/usr/local/cdh/hadoop/src/c++/libhdfs -I/usr/java/default/include/linux" cd scribe-2.2 ./bootstrap.sh --enable-hdfs --with-boost=/my_server/boost-1.41.0 --with-thriftpath=/my_server/thrift-0.4.0 --with-fb303path=/my_server/fb303 --prefix=/my_server/scribe-2.2 --with-hadooppath=/usr/local/cdh/hadoop make make install bin/scribed -c scribe.conf python client.py "Samag test string" 100 echo "Samag test string" | ./scribe_cat default ./scribe_ctrl reload 1463 /bin/hadoop fs -rm /testfiles/*.* /bin/hadoop fs -put /home/user/savgor/test.txt /data $ wget http://dist.apache.org/repos/dist/release/thrift/0.9.0/thrift-0.9.0.tar.gz $ tar xfz thrift-0.9.0.tar.gz $ cd thrift-0.9.0/ $ ./configure $ make $ sudo make install $ wget http://www.eu.apache.org/dist/hbase/hbase-0.94.2/hbase-0.94.2.tar.gz $ tar xfz hbase-0.94.2.tar.gz HBase.rootdir file:///hbase-0.94.2 $ ./hbase-0.94.2/bin/start-hbase.sh $ thrift --gen php hbase-0.94.2/src/main/apache/hadoop/hbase/thrift/hbase.thrift /bin/hbase thrift start $ ./hbase-0.94.2/bin/hbase shell HBase(main):001:0> create 'samag', 'hbase', 'test' HBase(main):002:0> put 'samag', 'test!', 'hbase:type1', 'string 1' HBase(main):003:0> put 'samag', 'test!', 'test:type2', ' string 2' HBase(main):004:0> exit ----------------------------------------------------------------------------------------------------------------- Web Speech API – чудо от HTML5. Распознавание речи на веб-странице Кирилл Сухов Web Speech API var voice = new webkitSpeechRecognition(); voice.onstart = function() { console.log("Говорите, Вас слушают!"); $('#bigButton').unbind('click'); $('#bigButton').bind( 'click', function(){ voice.stop();}); $('#bigButton')[0].value = "Остановить распознавание" } voice.stop = function() { $('#bigButton').unbind('click'); $('#bigButton').bind( 'click', function(){ voice.start();}); $('#bigButton')[0].value = "Начать распознавание" } voice.onresult = function() { } voice.error = function() { console.log("Error!"); } } $(function(){ $('#bigButton').bind( 'click', function(){voice.start();}); }); voice.onresult = function(event) { voice.onresult = function(event) { alert(event.results[0][0].transcript); } var voice = new webkitSpeechRecognition(); voice.continuous = true;
voice.onresult = function(event) { var messages = ''; for(var i = 0; i < event.results.length; i++) { messages += event.results[i][0].transcript; } $("#messageList").text(messages); } } else { var voice = new webkitSpeechRecognition(); voice.continuous = true; voice.interimResults = true; recognition.onerror = function(event) { if (event.error == 'no-speech') { console.log('Речь не опознается'); } if (event.error == 'audio-capture') { console.log('Отсутствует микрофон!'); } if (event.error == 'not-allowed') { console.log('Нет доступа к устройству'); } if (event.error == 'aborted') { console.log('Сигнал прерван!'); } if (event.error == 'network') { console.log('Отсутствует сетевое подключение'); } if (event.error == 'service-not-allowed') { console.log('Сервис не доступен'); } if (event.error == 'language-not-supported') { console.log('Язык не поддерживается'); } if (event.error == 'bad-grammar') { console.log('В школу, неуч!'); } };
$(function(){ $('#bigButton').bind( 'click', function(){ voice.start();}); $(".flag").live("click", function(){ $(".aflag").removeClass("aflag").addClass("flag"); $target = $(this); $target.addClass("aflag").removeClass("flag"); voice.lang = $target.data('lang'); }); }); ----------------------------------------------------------------------------------------------------------------- Система обмена сообщениями на MongoDB. Часть 1. Общее описание Александр Календарев $mongo > show dbs $mongo > help $mongo > db.help() $mongo > db.foo.help() > show dbs > use messages > show collections > db.folders.insert({user_id:1 , name:"Common" }) > db.folders.insert({user_id:2 , name:"Deleted" }) > db.folders.insert({user_id:2 , name:"Common" }) > db.folders.find() db.<имя коллекции>.find() db.<имя коллекции>.findOne() > db.folders.find({user_id:1}); > db.folders.find({user_id:2, name:"Common"}); SELECT * FROM foldes WERE user_id=2 AND name="Common" > db.folders.ensureIndex({"user_id":1}); db.folders.find({a:1, b:2 }); db.folders.find({a:1, b:2 , c:”xxx”}); db.folders.find({ b:2, a:1 }); db.folders.find({b:2, c:”xxx”}); > db.folders.insert({user:{id:1,name: "Alex"}, folders: [{name:"Common", count:1}, {name:"Favorite", count:3}] }) > db.folders.insert({user:{id:2,name: "Bob"}, folders: [{name:"Common", count:11}, {name:"Favorite", count:13}] }) >db.folders.find({ "user.name" : "Bob" }) >db.folders.find({ "folders.name" :"Common"}) >db.folders.find({ "user.id" : {$gt : 10}}).limit(10) > db.folders.find( { "status": {$exists: true }}) > db.folders.find( { "folders.name": {$in: ["Deleted"] }}) ----------------------------------------------------------------------------------------------------------------- Борьба со сложностью: таблицы решений Алексей Вторников если <идет дождь> то <взять зонтик> если <идет дождь> то <взять зонтик> иначе <открыть пиво> // Java boolean rainy = true; if (rainy) { System.out.println («Взять зонтик»); } else { System.out.println («Открыть пиво»); } // Oracle PL/SQL declare rainy number := 1; begin case rainy when 1 then DBMS_OUTPUT.PUT_LINE (‘Взять зонтик’); else DBMS_OUTPUT.PUT_LINE (‘Открыть пиво’); end case; end; // Lisp (cond ((eq rainy 1) eval umbrella) (t eval beer) ) GOTO (1000, 2000, 3000, 4000) I ... 1000 ... 2000 ... 3000 ... 4000 ... сумма_больше_250 && возраст_между_18_и_70 && имеется_обеспечение сумма_больше_250 && возраст_между_18_и_70 && ~ имеется_обеспечение сумма_больше_250 && ~возраст_между_18_и_70 && имеется_обеспечение if (сумма > 250000.00 && возраст в диапазоне от 18 до 70 лет && имеется обеспечение) передать_на_дальнейшее_рассмотрение (); else if (сумма > 250000.00 && возраст в диапазоне от 18 до 70 лет && ~имеется обеспечение) отказать (); // Остальные 6 альтернатив ... end; switch (condition) { case 7: передать_на_дальнейшее_рассмотрение (); break; case 6: отказать (); break; // Остальные 6 альтернатив ... case 0: отказать (); break; } -----------------------------------------------------------------------------------------------------------------