OpenStack Keystone. Знакомство с сервисом идентификации Андрей Маркелов # yum -y install epel-release # yum install -y https://rdo.fedorapeople.org/rdo-release.rpm # systemctl stop NetworkManager.service # systemctl disable NetworkManager.service # systemctl start network.service # systemctl enable network.service # systemctl disable firewalld.service # systemctl stop firewalld.service # yum -y install openstack-selinux SELINUX=enforcing SELINUX=disabled # yum -y install rabbitmq-server # systemctl start rabbitmq-server.service # systemctl enable rabbitmq-server.service # rabbitmqctl list_users # rabbitmqctl change_password guest openstack [{rabbit, [{loopback_users, []}]}] # systemctl restart rabbitmq-server.service # /usr/lib/rabbitmq/bin/rabbitmq-plugins enable rabbitmq_management # systemctl restart rabbitmq-server # yum -y install openstack-keystone openstack-utils # openstack-db --init --service keystone # systemctl enable mariadb.service # export ADM_TOKEN=$(openssl rand -hex 10) # crudini --set /etc/keystone/keystone.conf DEFAULT admin_token $ADM_TOKEN # keystone-manage pki_setup --keystone-user keystone --keystone-group keystone # chown -R keystone.keystone /etc/keystone/ssl/ # systemctl enable openstack-keystone.service # systemctl start openstack-keystone.service unset OS_USERNAME OS_TENANT_NAME OS_PASSWORD OS_AUTH_URL # Указываем содержимое $ ADM_TOKEN export SERVICE_TOKEN=1f31e3bc20d87af8329e # Указываем точку входа сервиса Keystone export SERVICE_ENDPOINT=http://os1.test.local:35357/v2.0 # source keystonerc_adm # keystone service-create --name keystone --type identity --description "OpenStack Identity Service" # keystone endpoint-create --service-id bdf6b82c788f4a6893f19e1bc747b219 --publicurl http://os1.test.local:5000/v2.0 --internalurl http://os1.test.local:5000/v2.0 --adminurl http://os1.test.local:35357/v2.0 # keystone user-create --name admin --email root@os1.test.local --pass openstack # keystone role-create --name admin # keystone tenant-create --name admin --description "Admin Tenant" # keystone user-role-add --user admin --tenant admin --role admin unset OS_USERNAME OS_TENANT_NAME OS_PASSWORD OS_AUTH_URL SERVICE_TOKEN SERVICE_ENDPOINT export OS_AUTH_URL=http://os1.test.local:35357/v2.0/ export OS_USERNAME=admin export OS_TENANT_NAME=admin export OS_PASSWORD=openstack # source keystonerc_adm # keystone tenant-create --name demo --description "Demo Tenant" # keystone user-create --name demo --tenant demo --pass openstack --email user@os1.test.local # keystone user-role-list --user demo --tenant demo unset OS_USERNAME OS_TENANT_NAME OS_PASSWORD OS_AUTH_URL SERVICE_TOKEN SERVICE_ENDPOINT export OS_AUTH_URL=http://os1.test.local:5000/v2.0/ export OS_USERNAME=demo export OS_TENANT_NAME=demo export OS_PASSWORD=openstack # keystone tenant-create --name service --description "Service Tenant" ----------------------------------------------------------------------------------------------------------------- Инструменты управления множеством контейнеров Docker Денис Силаков include 'docker' docker::image { 'ubuntu': image_tag => 'precise' } docker::run { 'test_machine1': image => 'wordpress', links => ['mysql:db'], volumes => ['/var/log'], memory_limit => 1g, cpuset => ['0'], hostname => 'my.wordpress.ru', dns => ['8.8.8.8'], env => ['VAR1=FOO', 'VAR2=BAR'], pull_on_start => false, } # curl -L https://github.com/docker/compose/releases/ download/1.1.0/docker-compose-Linux-x86_64 > /usr/local/bin/docker-compose # chmod +x /usr/local/bin/docker-compose web: image: wordpress ports: - "5080:80" links: - db:mysql db: image: mysql environment: MYSQL_DATABASE: wordpress MYSQL_ROOT_PASSWORD: password # docker-compose up -d docker-compose start db # docker-compose scale web=5 $ docker-machine create -d digitalocean --digitalocean-access-token=my_secret my_server $ eval "$(docker-machine env my_server)" $ docker run python $ docker run ubuntu # docker run -p 5000:5000 registry # service docker-registry start # curl http://localhost:5000 # docker pull python # docker tag python latest # docker push localhost:5000/python ----------------------------------------------------------------------------------------------------------------- Уборка файлового мусора Игорь Орещенков fsutil behavior query disablelastaccess fsutil behavior set disablelastaccess 0 Rem папка с файлами для обработки Const SRCFOLDER = "Z:\SRCFOLDER" Rem папка с архивом Const TGTFOLDER = "Z:\TGTFOLDER" Rem возраст файлов в днях, старше которого подлежат архивированию Const AGE = 550 Dim fso, file Set fso = CreateObject ("Scripting.FileSystemObject") If CheckParameters Then WScript.Echo "ARCHIVATION STARTED: " & now WScript.Echo "SRCFOLDER: " & SRCFOLDER HandleFolder (SRCFOLDER) WScript.Echo "ARCHIVATION FINISHED: " & now End If Rem ======================================= Rem Рекурсивный обход дерева папок. Rem Вызов: flrpath – путь к папке. Rem Возврат: True – папку можно удалять, Rem False – папку нужно оставить. Rem ======================================= Function HandleFolder (flrpath) Dim flr, sfs, rmf, n Rem рассматриваемая папка Set flr = fso.GetFolder (flrpath) Rem папки, вложенные в рассматриваемую папку Set items = flr.SubFolders Rem разрешение на удаление рассматриваемой папки rmf = False n = items.Count ' количество вложенных папок ... Rem Рекурсивный перебор папок, вложенных Rem в рассматриваемую папку For Each f in items flrname = flrpath & "\" & f.name If HandleFolder (flrname) Then If RemoveFolder (flrname) Then rmf = True n = n - 1 WScript.Echo " Successful folder removing: " & flrname Else WScript.Echo " Error folder removing: " & flrname End If End If Next Rem Перебор файлов, находящихся в рассматриваемой папке. Set items = flr.Files WScript.Echo " Handling folder: " & flrpath n = n + items.Count ' ... и количество вложенных файлов For Each f in items If SuitedFile (f) Then If HandleFile (f) Then WScript.Echo " Successful file handling: " & flrpath & "\" & f.name rmf = True n = n - 1 Else WScript.Echo " Error file handling: " & flrpath & "\" & f.name End If End If Next Rem Завершение обработки содержимого текущей папки. Set items = Nothing Set flr = Nothing Rem Принятие решения о возможности удаления обработанной папки HandleFolder = rmf And n = 0 End Function Rem =========================================== Rem Проверка параметров файла с точки зрения Rem необходимости помещения в архив. Rem Вызов: f – проверяемый файл. Rem Возврат: True – поместить файл в архив, Rem False – не помещать файл в архив. Rem =========================================== Function SuitedFile (f) Dim tn, agec, agem, agea, mage tn = Now Rem Определение возрастов создания/изменения/доступа. agec = tn - f.DateCreated agem = tn - f.DateLastModified agea = tn - f.DateLastAccessed Rem Определение минимального "возраста" файла. mage = agec If agem < mage Then mage = agem If agea < mage Then mage = agea SuitedFile = mage > AGE End Function Rem ========================================= Rem Перемещение в архив указанного файла. Rem Вызов: f – файл, подлежащий обработке. Rem Возврат: True – файл помещён в архив, Rem False – ошибка обработки файла. Rem ========================================= Function HandleFile (f) Dim res, dfpath dfpath = TGTFOLDER & Mid (f.ParentFolder.path, Len (SRCFOLDER) + 1) res = CreateFolder (dfpath) If res Then res = MoveFile (f, dfpath) End If HandleFile = res End Function Rem ======================================================= Rem Создание папки (а при необходимости – иерархии папок). Rem Вызов: fldrpath – путь к создаваемой папке. Rem Возврат: True – папка создана, Rem False – ошибка создания папки. Rem ======================================================= Function CreateFolder (fldrpath) Dim res, p, en res = False Rem путь длинее буквы носителя с двоеточием? If Len (fldrpath) > 2 Then If Not fso.FolderExists (fldrpath) Then Rem Определение пути к папке, Rem в которую вложена папка fldrpath. p = Len (fldrpath) Do While p > 2 and Mid (fldrpath, p, 1) <> "\" p = p - 1 Loop Rem Создание родительской папки. If CreateFolder (Left (fldrpath, p - 1)) Then On Error Resume Next fso.CreateFolder (fldrpath) en = Err.Number On Error GoTo 0 res = en = 0 End If Else res = True End If Else res = fso.FolderExists (fldrpath & "\.") End If CreateFolder = res End Function Rem ======================================================= Rem Перемещение файла с возвратом результата операции. Rem Вызов: f – перемещаемый файл, Rem flrpath – полный путь к папке назначения. Rem Возврат: True – файл перемещён, Rem False – при перемещении файла произошла ошибка. Rem ======================================================== Function MoveFile (f, flrpath) Dim en ' код ошибки On Error Resume Next f.Move flrpath & "\" en = Err.Number On Error GoTo 0 MoveFile = en = 0 End Function Rem ==================================================== Rem Удаление папки с возвратом результата операции. Rem Вызов: flrname – имя удаляемой папки. Rem Возврат: True – папка удалена, Rem False – при удалении папки произошла ошибка. Rem ===================================================== Function RemoveFolder (flrname) Dim en On Error Resume Next fso.DeleteFolder flrname, True en = Err.Number On Error GoTo 0 RemoveFolder = en = 0 End Function Rem =================================================== Rem Проверка входных параметров сценария архивирования. Rem Возврат: True – параметры в норме, Rem False – недопустимые параметры. Rem =================================================== Function CheckParameters Dim res, sf, tf res = True If Not fso.FolderExists (SRCFOLDER) Then Rem Папка с файлами для архивирования не существует. WScript.Echo "FATAL ERROR. Source folder doesn't exists: " & SRCFOLDER res = False Else sf = UCase (SRCFOLDER) + "\" tf = UCase (TGTFOLDER) + "\" If Len (sf) > Len (tf) Then If Left (sf, Len (tf)) = tf Then Rem Папка для размещения архива не может быть Rem вложена в папку с файлами для архивирования WScript.Echo "FATAL ERROR. Target folder can't be a part of the source folder." res = False End If Else If Left (tf, Len (sf)) = sf Then Rem Папка с файлами для архивирования не может Rem быть вложена в папку для размещения архива WScript.Echo "FATAL ERROR. Source folder can't be a part of the target folder." res = False End If End If End If CheckParameters = res End Function HandleFile = CreateFolder (dfpath) And MoveFile (f, dfpath) cscript.exe fclean.vbs > fclean.log ----------------------------------------------------------------------------------------------------------------- Демон BSD на острове пингвинов: перестроение огненных стен Рашид Ачилов 00100 allow ip from any to any via lo0 00400 deny ip from 10.54.200.0/24 to any in via em0 00420 deny log logamount 100 ip from any to table(12) via em0 00500 divert 8668 ip from any to any via em0 00505 deny log logamount 100 ip from table(12) to any via em0 00900 allow tcp from any to me dst-port 22 00905 allow tcp from me 22 to any 01855 allow log logamount 100 tcp from me to any dst-port 22 01860 allow log logamount 100 tcp from any 22 to me 03220 allow tcp from { me or 10.54.200.0/24 } to any dst-port 5190,5222 03225 allow tcp from any 5190,5222 to { me or 10.54.200.0/24 } 03590 allow ip from { me or 10.54.200.0/24 } to table(6) 03595 allow ip from table(6) to { me or 10.54.200.0/24 } 03915 allow tcp from 10.54.200.0/24 to me dst-port 25,110 04710 allow udp from { me or table(6) } to any dst-port 33434-33498 # ipset create set01 hash:ip # service ipset save create rfc1918 hash:net family inet hashsize 1024 maxelem 65536 add rfc1918 10.0.0.0/8 add rfc1918 172.16.0.0/12 add rfc1918 192.168.0.0/16 ${fwcmd} table 12 add 10.0.0.0/8 12 ${fwcmd} table 12 add 172.16.0.0/12 12 ${fwcmd} table 12 add 192.168.0.0/16 12 create me hash:ip family inet hashsize 1024 maxelem 65536 add me 212.20.5.1 add me 10.54.200.1 create table6 hash:ip family inet hashsize 1024 maxelem 65536 add me 170.70.70.1 add me 180.80.80.1 *filter :INPUT DROP [0:0] :FORWARD DROP [0:0] :OUTPUT DROP [0:0] # Разрешаем localhost interface -A INPUT -i lo -j ACCEPT -A OUTPUT -o lo -j ACCEPT *nat :POSTROUTING ACCEPT [0:0] -A POSTROUTING -o eth1 -j SNAT --to-source 212.20.5.1 natd_enable="YES" natd_interface="em0" natd_flags="-config /etc/natd.conf" allow ip from any to any via lo0 -A INPUT -i lo -j ACCEPT -A OUTPUT -o lo -j ACCEPT deny ip from 10.54.200.0/24 to any in via em0 -A OUTPUT -o eth1 -p all -s 10.54.200.0/24 -j DROP deny log logamount 100 ip from any to table(12) via em0 -A INPUT -i eth1 -m set –match-set rfc1918 dst -j LOG -A INPUT -i eth1 -m set –match-set rfc1918 dst -j DROP deny log logamount 100 ip from table(12) to any via em0 -A OUTPUT -o eth1 -m set –match-set rfc1918 src -j DROP allow tcp from any to me dst-port 22 -A INPUT -p tcp –-dport 22 -j ACCEPT allow tcp from me 22 to any -A OUTPUT -p tcp –-sport 22 -j ACCEPT allow log logamount 100 tcp from me to any dst-port 22 -A OUTPUT -p tcp -m set –match-set me src –dport 22 -j ACCEPT allow log logamount 100 tcp from any 22 to me -A INPUT -p tcp –sport 22 -m set –match-set me dst -j ACCEPT allow tcp from { me or 10.54.200.0/24 } to any dst-port 5190,5222 -A OUTPUT -p tcp -m set –match-set me src -m multiport –destination-port 5190,5222 -j ACCEPT -A FORWARD -p tcp -s 10.54.200.0/24 -m multiport –destination-port 5190,5222 -j ACCEPT allow tcp from any 5190,5222 to { me or 10.54.200.0/24 } -A INPUT -p tcp -m multiport –source-port 5190,5222 -m set –match-set me dst -j ACCEPT -A FORWARD -p tcp -m multiport –source-port 5190,5222 -d 10.54.200.0/24 -j ACCEPT allow ip from { me or 10.54.200.0/24 } to table(6) -A OUTPUT -p all -m set –match-set me src -m set –match-set table6 dst -j ACCEPT -A FORWARD -p all -s 10.54.200.0/24 -m set –match-set table6 dst -j ACCEPT allow ip from table(6) to { me or 10.54.200.0/24 } -A INPUT -p all -m set –match-set table6 src -m set –match-set me dst -j ACCEPT -A FORWARD -p all -m set –match-set table6 src -d 10.54.200.0/24 -j ACCEPT allow tcp from 10.54.200.0/24 to me dst-port 25,110 -A INPUT -p tcp -s 10.54.200.0/24 -m set –match-set me dst -m multiport –destination-port 25,110 -j ACCEPT allow udp from { me or table(6) } to any dst-port 33434-33498 -A OUTPUT -p udp -m set –match-set me –dport 33434:33498 -j ACCEPT -A FORWARD -p udp -m set –match-set table6 –dport 33434:33498 -j ACCEPT 00430 deny ip from any to table(12) via em0 00500 divert 8668 ip from any to any via em0 00505 deny ip from table(12) to any via em0 -A PREROUTING -p tcp -i eth1 -d 212.20.5.1 --dport 1723 -j DNAT --to-destination 10.54.200.5 *mangle -A PREROUTING -i eth1 -m set --match-set rfc1918 src -j MARK --set-mark 1 *filter -A INPUT -m mark --mark 1 -j DROP ----------------------------------------------------------------------------------------------------------------- Active Directory и безопасность. Часть 8. Защита станций привилегированных пользователей Леонид Шапиро Computer Configuration\Policies\Windows Settings\Local Policies\Security Options\Interactive logon: Require smart card Computer Configuration\Policies\Windows Settings\Security Settings\Local Policies\User Rights Assignment Computer Configuration\Policies\Windows Settings\Administrative Templates\System\Removable Storage Access Computer Configuration\Policies\Windows Settings\Security Settings\Application Control Policies\AppLocker ----------------------------------------------------------------------------------------------------------------- Эффективность индексов. Опыт использования индексов в Oracle Владимир Тихомиров, Валерий Михеичев Select table_owner, table_name, status, owner index_owner, index_name, index_type, distinct_keys, case when distinct_keys>0 then round(100/distinct_keys,1) else 0 end select_index, compression, visibility, clustering_factor, leaf_blocks, num_rows, tablespace_name index_tablespace_name, partitioned, global_stats, uniqueness, blevel, segment_created from all_indexes where table_owner='ИМЯ СХЕМЫ' and table_name='ИМЯ ТАБЛИЦЫ' order by index_name; ALTER INDEX ИМЯ ИНДЕКСА REBUILD ONLINE ALTER INDEX ИМЯ ИНДЕКСА REBUILD PARALLEL (DEGREE 4) NOLOGGING ONLINE Select t.owner table_owner, t.table_name, c.index_owner, c.index_name, c.column_name, c.column_position, t.num_distinct distinct_key_colum, case when t.num_distinct>0 then round(100/t.num_distinct,0) else 0 end select_column,t.histogram from all_ind_columns c, all_tab_columns t where t.owner=c.index_owner and t.table_name=c.table_name and t.column_name=c.column_name and c.index_owner='ИМЯ СХЕМЫ ИНДЕКСА' and c.index_name='ИМЯ ИНДЕКСА' order by c.index_name, c.column_position; Select owner, table_name, column_name, histogram from dba_tab_col_statistics where owner='ИМЯ СХЕМЫ' and table_name=’ИМЯ ТАБЛИЦЫ’ Select table_owner, table_name, owner index_owner, index_name, case when num_rows>0 then round(sample_size*100/num_rows,1) else 0 end Pr_stat, sample_size, num_rows, Last_analyzed, leaf_blocks, blevel from all_indexes where table_owner='ИМЯ СХЕМЫ ИНДЕКСА' and index_name='ИМЯ ИНДЕКСА'; EXECUTE DBMS_STATS.GATHER_INDEX_STATS ('ИМЯ СХЕМЫ, 'ИМЯ ИНДЕКСА', NULL, PS, NULL, NULL) Select * from DBA_IND_PARTITIONS where index_owner='ИМЯ_СХЕМЫ' and index_name='ИМЯ_ИНДЕКСА'; /*+ opt_param('optimizer_index_cost_adj' 1) */ /*+ optimizer_index_caching(10) */ Select * from v$parameter where name like '%index%'; Select a.ksppinm ,b.ksppstvl ,a.ksppdesc from x$ksppi a,x$ksppcv b,x$ksppsv c where a.indx = b.indx and a.indx = c.indx and a.ksppinm like '%index%'; Select i.owner, i.table_name, i.index_name, round(s.bytes/1024/1024) mb from dba_segments s, dba_indexes I where s.owner=i.owner and s.segment_name=i.index_name and i.owner='ИМЯ СХЕМЫ' and i.table_name ='ИМЯ ТАБЛИЦЫ'; Select s.owner, d.table_name, d.column_name, s.segment_name, s.segment_type, s. bytes, s.tablespace_name from DBA_SEGMENTS s, DBA_LOBS d where s.segment_name in (d.segment_name, d.index_name) and s.owner=d.owner and d.owner='ИМЯ СХЕМЫ' and d.table_name='ИМЯ ТАБЛИЦЫ' and segment_type like '%INDEX%' order by 3; Select i.owner table_owner, i.table_name,p.index_owner, p.index_name, p.partition_name partition_index, p.partition_position pos, p.num_rows index_num_rows, (select round(s.bytes/1024/1024) from dba_segments s where s.partition_name=p.partition_name and s.segment_type='INDEX PARTITION') mb from dba_ind_partitions p, dba_indexes I where p.index_name=i.index_name and i.owner='ИМЯ СХЕМЫ' and i.table_name ='ИМЯ ТАБЛИЦЫ' order by p.partition_position; Select i.status, i.owner, i.index_name, o.object_type, i.table_owner, i.table_name, o.last_ddl_time, i.last_analyzed,o.created from dba_indexes i, dba_objects o where i.owner=o.owner and i.index_name=o.object_name and o.object_type='INDEX' and greatest(last_ddl_time, last_analyzed)>sysdate-1/24 and i.status='UNUSABLE' Select table_owner, table_name, owner index_owner, index_name, tablespace_name tablespace_index from dba_indexes where owner not like '%SYS%' and tablespace_name='SYSTEM' order by 1 Select i.table_owner, i.table_name, p.object_owner index_owner, p.object_name index_name, p.operation, max(p.options), max(p.cost) costs, max(p.cpu_cost) cpu_cost from v$sql_plan p, dba_indexes i where i.owner=p.object_owner and i.index_name=p.object_name and p.operation ='INDEX' and p.options like '%FULL%' and p.object_owner not like 'SYS' group by i.table_owner, i.table_name, p.object_owner, p.object_name, p.operation order by 7 desc ----------------------------------------------------------------------------------------------------------------- Rack – основа веб-фреймворков в Ruby Иван Шихалев $ sudo gem install rack require 'pp' require 'rack' app = proc do |env| [ 200, { 'Content-Type' => 'text/plain' }, [ env.pretty_inspect ] ] end Rack::Handler::WEBrick.run app $ ruby demo01.rb require 'pp' app = proc do |env| [ 200, { 'Content-Type' => 'text/plain' }, [ env.pretty_inspect ] ] end run app $ rackup demo01.ru app = proc do |env| req = Rack::Request.new env [ 200, { 'Content-Type' => 'text/plain' }, [ req.params.pretty_inspect ] ] end $ rackup demo02.ru app = proc do |env| req = Rack::Request.new env res = Rack::Response.new res['Content-Type'] = 'text/plain' res.write req.params.pretty_inspect res.finish end class Log def initialize app, output = $stderr @app = app @output = output end def call env @output.puts env.pretty_inspect @app.call env end end json = proc do |env| [ 200, { 'Content-Type' => 'application/json' }, [ JSON.generate(env) ] ] end txt = proc do |env| [ 200, { 'Content-Type' => 'text/plain' }, [ env.pretty_inspect ] ] end app = Rack::Builder.app do use Log map '/js/' do run json end run txt end run app use Log map '/js/' do run json end run txt ----------------------------------------------------------------------------------------------------------------- Многообразие решений задачи построения ряда Фибоначчи на примере особенностей PHP 5.6 Александр Майоров function fib($n) { if ($n < 2) return $n; return fib($n-1) + fib($n-2); } for ($n=0;$n<30;$n++) var_dump(fib($n)); function fib($n) { return $n < 2 ? $n : fib($n-1) + fib($n-2); } function fib($n) { static $memo = []; if ($n < 2) return $n; if (!empty($memo[$n])) return $memo[$n]; return $memo[$n] = fib($n - 1) + fib($n - 2); } function fib($n) { $prev = $curr = 1; if ($n < 2) return $n; for ($i = 3; $i <= $n; $i++) { $newc = $prev + $curr; $prev = $curr; $curr = $newc; } return $curr; } for ($n=0;$n<100;$n++) var_dump(fib($n)); function fib($n) { static $memo = []; if ($n < 2) return $n; if (!empty($memo[$n])) return $memo[$n]; $prev = $curr = 1; for ($i = 3; $i <= $n; $i++) { $newc = $prev + $curr; $prev = $curr; $curr = $newc; } return $memo[$n] = $curr; } function fib() { static $key =-1, $prev = 0, $curr = 1; ++$key; if ($key < 2) return $key; $curr = $prev + $curr; $prev = $curr - $prev; return $curr; } for ($n=0;$n<100;$n++) var_dump( fib() ); list ($a, $b) = array($b, $a) function fib() { static $key =-1, $prev = 0, $curr = 1; ++$key; if ($key < 2) return $key; list ($prev, $curr) = [ $curr, $prev + $curr ]; return $curr; } function fib(){ $curr = ($prev = 0) +1; yield $prev; yield $curr; while (true){ list ($prev, $curr) = [$curr, $prev + $curr]; yield $curr; } } $i = 0; foreach (fib() as $fibonacci) { var_dump($fibonacci); if ($i++ > 100) break; } function fib() { list ($prev, $curr) = [0, 1]; yield $prev; for(;; list ($prev, $curr) = [$curr, $prev + $curr] ) yield $curr; } class Fibonacci implements Iterator { protected $_previous = 0, $_current = 1, $_key = 0; public function valid() { return true; } public function current() { if ($this->_key === 0) return $this->_previous; return $this->_current; } public function key() { return $this->_key; } public function next() { if ($this->_key++ > 0) { $newPrevious = $this->_current; $this->_current += $this->_previous; $this->_previous = $newPrevious; } } public function rewind() { $this->_previous = 0; $this->_current = 1; $this->_key = 0; } } $Fib = new Fibonacci; $i = 0; foreach ($Fib as $fibonacci) { var_dump($fibonacci); if ($i++ > 100) break; } trait Singleton { private static $__; private function __construct() {} public static function I() { self::$__ or self::$__ = new self; return self::$__; } } class Fib extends Fibonacci { use Singleton; } function fib() { return Fib::I(); } $i = 0; foreach (fib() as $fibonacci) { var_dump($fibonacci); if ($i++ > 100) break; } function fib($n){ $a = $b = $c = $rd = 1; $d = $rc = 0; while ($n){ // Если степень нечетная // Эта запись эквивалентна if ($n % 2 === 0){ if ($n & 1){ // Умножаем вектор R на матрицу A $tc = $rc; $rc = $rc * $a + $rd * $c; $rd = $tc * $b + $rd * $d; } // Умножаем матрицу A на саму себя $ta = $a; $tb = $b; $tc = $c; $a = $a * $a + $b * $c; $b = $ta * $b + $b * $d; $c = $c * $ta + $d * $c; $d = $tc * $tb + $d * $d; // Уменьшаем степень вдвое $n >>= 1; // Эта запись эквивалентна $n /= 2; } return $rc; } for ($n=0;$n<100;$n++) var_dump(fib($n)); function fib($n) { $sqrt5 = sqrt(5); $oprnd = (1 + $sqrt5) / 2; return round((pow($oprnd, $n + 1) - pow(1 - $oprnd, $n + 1)) / $sqrt5); } for ($n=0;$n<100;$n++) var_dump(fib($n)); static $sqrt5; $sqrt5 or $sqrt5 = sqrt(5); $oprnd = (1 + $sqrt5) / 2; return round((($oprnd ** ($n+1)) - ((1-$oprnd) ** ($n+1))) / $sqrt5); function fib($n) { $sqrt5 = sqrt(5); $oprnd = (1 + $sqrt5) / 2; return (($oprnd ** $n) - pow(-$oprnd, -$n) ) / $sqrt5; } function fib($n) { return round( 1.6180339887498948482 ** $n / 2.2360679774998 ); } function fib($count) { $fib = call_user_func(function(){ list ($prev, $curr) = [0, 1]; yield $prev; for(;; list ($prev, $curr) = [$curr, $prev + $curr] ) yield $curr; }); for ($i=0;$i<$count;$i++) $fib->next(); return $fib->current(); } for ($i=0;$i<100;$i++) var_dump(fib($i)); -----------------------------------------------------------------------------------------------------------------