2011-10-21

Удаление пользователей из OIM

Домученный скрипт по удалению удаленных пользователей из OIM. Из замеченных багов -- в отчетах все равно остаются записи об удаленных пользователях, если вместо них создается другой с тем же именем. Вероятно, проще было взять скрипт с forums.oracle.com (если порыться, там можно найти скрипты из нескольких DELETE).

Вполне вероятно в некоторых случаях скрипт работать не будет.

СНЯТЬ БЕКАП ПЕРЕД ЗАПУСКОМ!


set serveroutput on size 1000000

DROP TABLE ref_table;

CREATE TABLE ref_table(
table_name VARCHAR2(30) NOT NULL,
rid rowid NOT NULL PRIMARY KEY,
lvl NUMBER NOT NULL);


DECLARE
lLVL INTEGER := 0;
lROWS_QNT NUMBER;
i PLS_INTEGER;

function build_column_list(aCONSTRAINT_NAME VARCHAR2, aPREFIX VARCHAR2) RETURN VARCHAR2 IS
RESULT VARCHAR2(4000);
BEGIN
FOR rec IN (
SELECT *
FROM user_cons_columns
WHERE constraint_name = aCONSTRAINT_NAME
ORDER BY position
) LOOP
RESULT := RESULT || ',' || aPREFIX || rec.column_name;
END LOOP;
--dbms_output.put_line(LTRIM(RESULT, ','));
RETURN LTRIM(RESULT, ',');
END build_column_list;

FUNCTION process_reference(aLVL NUMBER, aTBL_NAME VARCHAR2, aFK_CONS VARCHAR2, aPAR_TABLE_NAME VARCHAR2, aPK_CONS VARCHAR2) RETURN NUMBER IS
LQNT NUMBER;
BEGIN
dbms_output.put_line('Обработка ссылки на уровне ' || aLVL || ' ' || aTBL_NAME || '.' || aFK_CONS || ' -> ' || aPAR_TABLE_NAME || '.' || aPK_CONS);
IF aTBL_NAME <> aPAR_TABLE_NAME THEN
EXECUTE IMMEDIATE '
UPDATE /*+ NO_INDEX(x)*/ref_table x
SET lvl = (
select max(lvl) + 1
FROM ' || aPAR_TABLE_NAME || ' pt, ref_table rt
WHERE rt.rid = pt.rowid
AND ( ' || build_column_list(aPK_CONS, 'pt.') || ') IN (SELECT ' || build_column_list(aFK_CONS, 't.') || ' FROM ' || aTBL_NAME || ' t)
)
WHERE (rid || '' '') IN (
SELECT /*+ NO_INDEX(t)*/ t.rowid || '' ''
FROM ' || aTBL_NAME || ' t
WHERE ( ' || build_column_list(aFK_CONS, 't.') || ')
IN (SELECT ' || build_column_list(aPK_CONS, 'pt.') || ' FROM ref_table rt, ' || aPAR_TABLE_NAME || ' pt WHERE rt.rid = pt.rowid))';
END IF;

dbms_output.put_line('Обновлено уровней: ' || SQL%ROWCOUNT);
EXECUTE IMMEDIATE '
INSERT INTO ref_table(table_name, rid, lvl)
SELECT ''' || UPPER(aTBL_NAME) || ''', t.rowid, :LVL + 1
FROM ' || aTBL_NAME || ' t
WHERE ( ' || build_column_list(aFK_CONS, 't.') || ')
IN (SELECT ' || build_column_list(aPK_CONS, 'pt.') || ' FROM ref_table rt, ' || aPAR_TABLE_NAME || ' pt WHERE rt.rid = pt.rowid)
AND NOT EXISTS (
SELECT NULL
FROM ref_table rt
WHERE rid = t.rowid)'
USING aLVL;
lQNT := SQL%ROWCOUNT;
dbms_output.put_line('Добавлено строк ' || lQNT);

RETURN lQNT;
END;

FUNCTION process_level(aLVL NUMBER) RETURN NUMBER IS
lQNT NUMBER := 0;
BEGIN
dbms_output.put_line('+++ level = ' || aLVL);
FOR rec IN (
SELECT DISTINCT f.table_name chi_table_name, f.constraint_name chi_table_cons,
pp.table_name par_table_name, pp.constraint_name par_table_cons
FROM user_constraints f, user_constraints pp
WHERE f.constraint_type = 'R'
AND f.r_constraint_name = pp.constraint_name
AND pp.table_name IN (SELECT upper(table_name) FROM ref_table WHERE lvl = aLVL)
) LOOP
lQNT := lQNT + process_reference(aLVL, rec.chi_table_name, rec.chi_table_cons, rec.par_table_name, rec.par_table_cons);
END LOOP;
RETURN lQNT;
END;
BEGIN
INSERT INTO ref_table(table_name, rid, lvl)
SELECT 'USR', u.rowid, 0
FROM usr u
WHERE u.usr_status = 'Deleted';

lROWS_QNT := process_level(lLVL);
dbms_output.put_line('Будет удалено на уровне ' || (lLVL + 1) || ' ' || lROWS_QNT || ' строк');
WHILE lROWS_QNT > 0 LOOP
lLVL := lLVL + 1;
lROWS_QNT := process_level(lLVL);
dbms_output.put_line('Будет удалено на уровне ' || (lLVL + 1) || ' ' || lROWS_QNT || ' строк');
END LOOP;

dbms_output.put_line('=========');
dbms_output.put_line('Удаление');
dbms_output.put_line('=========');

-- Удаляем
FOR rec IN (
SELECT DISTINCT table_name, lvl
FROM ref_table
ORDER BY lvl DESC
) LOOP
dbms_output.put_line('Удаляем записи из ' || rec.table_name || ' lvl = ' || rec.lvl);
EXECUTE IMMEDIATE '
delete from ' || rec.table_name || ' t
where t.rowid IN (SELECT rid FROM ref_table WHERE table_name = :TN AND lvl = :lvl)'
USING rec.table_name, rec.lvl;

dbms_output.put_line('Из таблицы ' || rec.table_name || ' удалено строк ' || SQL%ROWCOUNT);
END LOOP;
END;
/

2011-06-07

Шаблон расположения регионов в APEX

Для того, что бы посмотреть, где расположить регион на странице (display point), можно открыть любой регион, найти поле Display Point и нажать на фонарик рядом с полем

2011-05-22

Заполнение ссылки по кнопке в apex

В APEX коряво сделано заполнение ссылки, например с кнопки.
Так, если я хочу для кнопки Печать задать редирект на какую-то страницу, то галочку PRINTER_FRENDLY мне просто не куда будет ставить.

Правило для заполнения линков в APEX такое:
f?p=App:Page:Session:Request:Debug:ClearCache:itemNames:itemValues:PrinterFriendly
или, если с заполненными переменными примерно так
f?p=?&APP_ID.:НОМЕР_СТРАНИЧКИ_ДЛЯ_ССЫЛКИ:&SESSION.::&DEBUG.::VAR1,VAR2:&FROM_VAR1.,&FROM_VAR2:YES

Замечаем, что то, что мы пишем в значение поля Request при создании кнопки рассовывается по другим полям.
Поэтому:
1. указываем Page (страницу, куда мы переходим) - заполнение этого эквивалентно заполнению &APP_ID.:НОМЕР_СТРАНИЧКИ_ДЛЯ_ССЫЛКИ:&SESSION.

2. В Request прописываем остаток, например: :&DEBUG.:RIR:P20_SID:&P12_SID.:YES. Это правильно запонит остальные поля, в том числе и PrinterFriendly. Если необходимо, можно так же указать значение для Request в этой строке

2011-04-29

Борьба с ошибкой ORA-12560

При подключении sqlplus / as sysdba или с использованием listener sqlplus sys/syspassword@db возникает ошибка:
ORA-12560: TNS:ошибка адаптера протокола

Все шаги в совокупности дали желаемый результат.

1. Проверяем переменную ORACLE_SID (устанавливается или в переменных окружения или в реестре). Если переменная не установлена или установлена не правильно, этот шаг поможет при подключении без листенера sqlplus / as sysdba.

После исправления первого шага, возможно возникновение ошибки:
ORA-01031: insufficient privileges
Самая распространенная причина этого: необходимо прописать SQLNET.AUTHENTICATION_SERVICES = (NTS) в файле sqlnet.ora на сервере.

2. Для подключений через listener
Проверить, что в listener.ora прописаны правильные настройки. У меня все падало из-за неправильно выставленного
(SID_NAME=...)

После исправления и перезапуска все начало нормально подключаться

2011-04-23

Проблемы с Enterprise manager

На тестовой базе возникли проблемы с EM (хотя не посредстенно после создания базы он работал):

Enterprise Manager is not able to connect to the database instance. The state of the components are listed below.

Предлагаемые в итернете решения немного пугали, пока не найден кардинальный метод:

emca -deconfig dbcontrol db
emca -config dbcontrol db

Об именах

Исследования в статье натолкнули на мысль собственных исследований.

Итак в оракле есть имена и параметры:

  • db_name -- имя базы, т.е. физического набора файла данных. Имя базы по словам Кайта прописывается в самих файлах.

  • db_domain -- никогда особо не понимал, зачем это нужно

  • instance_name -- имя экземпляра, т.е. набора процессов операционной системы и памяти.

  • db_unique_name -- уникальное имя базы, если db_name одинаковый (например в Standby). Именно это имя используется в папках во Flash recovery area

  • service_name -- имя сервиса, реалезуемое на экземпляре.


Исследования проводим на Oracle 11.1.0.6 путем изменения параметров, перезапуска базы и исследования результатов путем запуска скрипта:

shut immediate
startup nomount pfile=d:\init.ora

set feedback off
alter system register;

--host cls

col "name" format a20
column value format a40
SELECT name, value FROM v$parameter where name IN ('db_name', 'db_unique_name', 'db_domain', 'instance_name', 'service_names');

host lsnrctl services


База изначально создавалась как db1.notebook, т.е.

*.db_name='db1'
*.db_domain='notebook'


1. db_name = db1, остальные параметры не заданы

db_domain
instance_name db1
service_names db1
db_name db1
db_unique_name db1

Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=IPC)(KEY=EXTPROC1521)))
Services Summary...
Service "db1" has 1 instance(s).
Instance "db1", status BLOCKED, has 1 handler(s) for this service...
Handler(s):
"DEDICATED" established:0 refused:0 state:ready
LOCAL SERVER
Service "db1_XPT" has 1 instance(s).
Instance "db1", status BLOCKED, has 1 handler(s) for this service...
Handler(s):
"DEDICATED" established:0 refused:0 state:ready
LOCAL SERVER


Без указания заданного при создании базы db_domain база нормально открылась

2. db_name = db2 (отличается от того, что задавался при создании)
NAME VALUE
-------------------- ----------------------------------------
db_domain
instance_name db1
service_names db2
db_name db2
db_unique_name db2

Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=IPC)(KEY=EXTPROC1521)))
Services Summary...
Service "db2" has 1 instance(s).
Instance "db1", status BLOCKED, has 1 handler(s) for this service...
Handler(s):
"DEDICATED" established:0 refused:0 state:ready
LOCAL SERVER
Service "db2_XPT" has 1 instance(s).
Instance "db1", status BLOCKED, has 1 handler(s) for this service...
Handler(s):
"DEDICATED" established:0 refused:0 state:ready
LOCAL SERVER
The command completed successfully


instance_name берется откуда-то еще, возможно из каких-то переменных среды или из сервиса
База не маунтится.

SQL> alter database mount;
alter database mount
*
ERROR at line 1:
ORA-01103: database name 'DB1' in control file is not 'DB2'


3. db_name=db1, db_domain=notebook

NAME VALUE
-------------------- ----------------------------------------
db_domain notebook
instance_name db1
service_names db1.notebook
db_name db1
db_unique_name db1

Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=IPC)(KEY=EXTPROC1521)))
Services Summary...
Service "db1.notebook" has 1 instance(s).
Instance "db1", status BLOCKED, has 1 handler(s) for this service...
Handler(s):
"DEDICATED" established:0 refused:0 state:ready
LOCAL SERVER
Service "db1_XPT.notebook" has 1 instance(s).
Instance "db1", status BLOCKED, has 1 handler(s) for this service...
Handler(s):
"DEDICATED" established:0 refused:0 state:ready
LOCAL SERVER
The command completed successfully


Таким образом service_name = db_name + db_domain

4. db_name=db1, db_domain=notebook, service_names = my_service

NAME VALUE
-------------------- ----------------------------------------
db_domain notebook
instance_name db1
service_names my_service
db_name db1
db_unique_name db1

Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=IPC)(KEY=EXTPROC1521)))
Services Summary...
Service "db1.notebook" has 1 instance(s).
Instance "db1", status BLOCKED, has 1 handler(s) for this service...
Handler(s):
"DEDICATED" established:0 refused:0 state:ready
LOCAL SERVER
Service "db1_XPT.notebook" has 1 instance(s).
Instance "db1", status BLOCKED, has 1 handler(s) for this service...
Handler(s):
"DEDICATED" established:0 refused:0 state:ready
LOCAL SERVER
Service "my_service.notebook" has 1 instance(s).
Instance "db1", status BLOCKED, has 1 handler(s) for this service...
Handler(s):
"DEDICATED" established:0 refused:0 state:ready
LOCAL SERVER
The command completed successfully


service_names равен соответствующему параметру

5. db_name=db1, db_domain=notebook, instance_name = just_instance

NAME VALUE
-------------------- ----------------------------------------
db_domain notebook
instance_name just_instance
service_names db1.notebook
db_name db1
db_unique_name db1

Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=IPC)(KEY=EXTPROC1521)))
Services Summary...
Service "db1.notebook" has 1 instance(s).
Instance "just_instance", status BLOCKED, has 1 handler(s) for this service...

Handler(s):
"DEDICATED" established:0 refused:0 state:ready
LOCAL SERVER
Service "db1_XPT.notebook" has 1 instance(s).
Instance "just_instance", status BLOCKED, has 1 handler(s) for this service...

Handler(s):
"DEDICATED" established:0 refused:0 state:ready
LOCAL SERVER
The command completed successfully


instance_name поменялся и стал равен соответсвующему параметру.

6. db_name=db1, db_domain=notebook, db_unique_name=uniq

NAME VALUE
-------------------- ----------------------------------------
db_domain notebook
instance_name db1
service_names uniq.notebook
db_name db1
db_unique_name uniq

LSNRCTL for 32-bit Windows: Version 11.1.0.6.0 - Production on 23-APR-2011 02:47
:20

Copyright (c) 1991, 2007, Oracle. All rights reserved.

Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=IPC)(KEY=EXTPROC1521)))
Services Summary...
Service "uniq.notebook" has 1 instance(s).
Instance "db1", status BLOCKED, has 1 handler(s) for this service...
Handler(s):
"DEDICATED" established:0 refused:0 state:ready
LOCAL SERVER
Service "uniq_XPT.notebook" has 1 instance(s).
Instance "db1", status BLOCKED, has 1 handler(s) for this service...
Handler(s):
"DEDICATED" established:0 refused:0 state:ready
LOCAL SERVER
The command completed successfully


service_names = db_unique_name + db_domain

NAME VALUE
-------------------- ----------------------------------------
db_domain notebook
instance_name db1
service_names uniq.notebook
db_name db1
db_unique_name uniq

Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=IPC)(KEY=EXTPROC1521)))
Services Summary...
Service "uniq.notebook" has 1 instance(s).
Instance "db1", status BLOCKED, has 1 handler(s) for this service...
Handler(s):
"DEDICATED" established:0 refused:0 state:ready
LOCAL SERVER
Service "uniq_XPT.notebook" has 1 instance(s).
Instance "db1", status BLOCKED, has 1 handler(s) for this service...
Handler(s):
"DEDICATED" established:0 refused:0 state:ready
LOCAL SERVER
The command completed successfully


Выводы



1. service_names = COALESCE(service_names, db_unique_name || db_domain, db_name || db_domain) (точки писать не стал :))
2. instance_name = NVL(instance_name, что-то еще)
3. Без указания заданного при создании базы db_domain база нормально открылась

2011-04-21

Отслеживание процессов в Standby

Мониторниг передачи файлов на Primary:

  • V$ARCHIVED_LOG -- показывает, какие логи отправляются на STAND BY
  • V$ARCHIVE_DEST_STATUS -- состояние arch процессов, куда они отправляют файлы, последний отправленный файл
  • V$ARCHIVE_DEST -- аналогичен предыдущей вьюхе
  • alert log -- можно смотреть ошибки при отправке

Мониторниг приема и применения файлов в Standby

  • V$ARCHIVED_LOG (полученные логи), V$LOG_HISTORY (примененные логи), V$ARCHIVE_DEST_STATUS -- вьюхи, дающие с разным уровнем детализации последний полученный и последний применнный лог. Из последней вьюхи можно узнать ,в каком режиме применяются логи (real time или нет) в колонке RECOVERY_MODE.
  • Запущен ли процесс (должен существовать процесс MRP или MRP0)

SELECT PROCESS, STATUS FROM V$MANAGED_STANDBY;

  • V$DATAGUARD_STATUS -- информация из alert лога, можно узать полезное что-нибудь.

Для logical standby добавляются представления DBA_LOGSTDBY_*, V$LOGSTDBY_*

 

 

2011-04-18

Передача файлов

На StandBy необходимо сохранять следующие файлы:

  • архивы redo.log собственных (если logical standby)
  • архивы standby redo log (то, что передается с primary)
  • архивы переданных с primary архивов (если были проблемы со связью)
  • Отправлять никуда ничего не надо, до тех пор, пока база не получит роль Primary

В Primary необходимо

  • Делать архивы своих redo.log
  • Отправлять в stand by свои redo.log

Для управления этой кухней сделаны VALID_FOR (что сохраняем/отправляем, когда (при какой роли) сохраняем/отправляем)

Для что возможные значения: ONLINE_LOGFILE, STANDBY_LOGFILE, ALL_LOGFILES

Для когда возможные значения: PRIMARY_ROLE, STANDBY_ROLE, ALL_ROLES

Исходя из этого выводим:

1. Необходимо иметь возможность отправлять свои изменения по сети, т.е. должно быть настроено

VALID_FOR(ONLINE_LOGFILE, PRIMARY_ROLE) + указан сетевой сервис отправки

2. В качестве сохранения собственных изменений можно использовать Flash Recovery Area, которая по умолчанию настраивается в log_archive_dest_10. Если верить документации, то для log_archive_dest_10 будут настроены параметры по-умолчанию, т.е ALL_LOGFILES,ALL_ROLES. Но тут опять небольшая загвоздка в документации:

Flash recovery area destinations specified with the STANDBY_ARCHIVE_DEST parameter on logical standby databases (SQL Apply) are ignored

Таким образом, архивные логи, пришедшие с Primary в случае logical standby складировать некуда (если правильно понимаю документацию).

3. Т.к. ситуация со standby логами во flash recovery area в случае logical stand by не совсем понятна, возьмем, что оракл рекомендует использовать в документации:

Для Primary

LOG_ARCHIVE_DEST_1=
'LOCATION=/arch1/chicago/
VALID_FOR=(ALL_LOGFILES,ALL_ROLES)
LOG_ARCHIVE_DEST_2=
'LOCATION=/arch2/chicago/
VALID_FOR=(STANDBY_LOGFILES,STANDBY_ROLE)
STANDBY_ARCHIVE_DEST=/arch2/chicago/

Для Standby

LOG_ARCHIVE_DEST_1=
'LOCATION=/arch1/denver/
VALID_FOR=(ONLINE_LOGFILES,ALL_ROLES)
DB_UNIQUE_NAME=denver'
LOG_ARCHIVE_DEST_2=
'LOCATION=/arch2/denver/
VALID_FOR=(STANDBY_LOGFILES,STANDBY_ROLE)
STANDBY_ARCHIVE_DEST=/arch2/denver

Тут возникают непонятные моменты:

1. Почему log_archive_dest_1 на Primary и StandBy различаются.

2. А не складируются ли у нас Standby логи в Primary 2 раза, после смены ролей. Видимо в Primary должно быть:

LOG_ARCHIVE_DEST_1=
'LOCATION=/arch1/chicago/
VALID_FOR=(ONLINE_LOGFILES,ALL_ROLES)

Или же, если верить, что Flash Recorery Area и так сохраняет в себе все сгенеренные логи, достаточно добавить параметр STANDBY_ARCHIVE_DEST.

Наверное, лучше всего сконфигурировать 3 процесса и разбивать файлы на 2 кучки свои и чужие:

1. Посылатель файлов для Primary role

2. Раскладыватель online для всех ролей (1 кучка)

3. Раскладыватель standby логов для standby роли (вторая кучка). STANDBY_ARCHIVE_DEST, если не задан, будет указывать на вторую кучку аутоматически

Создание Standby общие идеи

На основании документации и статьи

Общие идеи

Подготовка primary

 

  1. База находится в режиме архивирования, есть password file.
  2. Перевести базу в режим force logging
  3. Опционально (если будет использоваться режим maximum protection и maximum aviablity, включен LGWR ASYNC transport mode). Этот случай не исследовался
  4. Изменить параметры базы данных. Можно делать alter system, можно через pfile с последующим перезапуском. Параметры применить перед снятием бекапа. Минимум параметров, которые необходимо задавать:
    • db_unique_name -- экземпляры открывают одну и туже базу данных, в которых db_name одинаковый. Параметры должны различаться в primary и standby. Что бы не было путаницы, лучше не называть с подчеркиваниями (oradim не может создать базу с sid содержащий подчеркивания), так же заводить в дальнейшем tnsnames с такой же строкой (service_name, совпадающий с идентификатором в tnsnames)
    • log_archive_config='dg_config=(db1_pri,db1_stb)' -- задаются db_unique_name, между которыми происходит обмен логами
    • LOG_ARCHIVE_DEST_1=  'SERVICE=db1stb VALID_FOR=(ONLINE_LOGFILES,PRIMARY_ROLE)  DB_UNIQUE_NAME=db1_stb'
      LOG_ARCHIVE_DEST_STATE_1=ENABLE - т.к. у меня есть db_recovery_file_dest, то log_archive_dest_2 мне (наверное, перепроверить при измении ролей!!!) не нужен. В SERVICE указывается строка из tnsnames. Указывает, куда отсылаем логи.
    • FAL_SERVER='DB1STB'
      FAL_CLIENT='DB1'
      STANDBY_FILE_MANAGEMENT=auto -- параметры, необходимые при смене ролей primary
    • т.к. структура каталогов standby и primary  у меня совпадает, то параметры log_file_name_convert и db_file_name_convert я не указываю ни в primary, ни в standby. Вместо этого при разворачивании пользуюсь ключиком NOFILENAMECHECK
  5. Сделать бекап, из которого будем разворачивать standby, включая специальный бекап control file.
  6. Настроить tnsnames, прописав туда саму базу и standby-базу. Проверить tnsping правильность.

Подготовка standby

  1. Забираем с primary файлы:
    • tnsname.ora -- должен указывать и на primary и на standby
    • password (можно забрать и переименовать, можно создать новый)
    • pfile
    • бекапы - помещаем в тоже место, куда снимались в primary, хотя можно и рекоталагизировать.
    • redo логи, если они были созданы в primary (этот случай не рассматривался)
  2. Изменяем pfile
    • изменяем db_unique_name, см. примечания к этому в primary
    • control_files -- я закомментировал и он у меня создал контрольник в db_recovery_file_dest. В документации просто изменены пути
    • LOG_ARCHIVE_DEST_1=  'SERVICE=db1 VALID_FOR=(ONLINE_LOGFILES,PRIMARY_ROLE) DB_UNIQUE_NAME=db1_pri'. Куда отправляем файлы в случае смены ролей. Относительно Primary изменилось SERVICE и DB_UNIQUE_NAME
  3. Создаем каталоги, аналогичные по структуре primary для указанных в файле параметров путей, а так же файлов базы данных.
  4. Создаем экземпляр при помощи oradim, создаем сервис listenera. При использовании oradim не получается создать sid базы с подчеркиванием. Проверить, что службы сами запускаются.
  5. Делаем или изменяем password file.
  6. Создаем spfile, Запускаем базу в режиме nomount. Если появляется ошибка ora-12560 сделать set oracle_sid = ...
  7. Разворачиваем созданный на primary бекап. Если структура каталогов та же, то используем команду duplicate target database for standby dorecover NOFILENAMECHECK, что бы не ругалась на дублирование имен файлов. Запускать rman необходимо на standby, или прописывать базу в листенере, что бы к ней можно было подключиться удаленно.
  8. Делаем alter database recover managed standby database disconnect;
  9. Проверяем передачу и накат логов.

2011-03-28

_small_table_threshold

Давно хотел посмотреть сам на этот механизм, но Льюис уже выложил тесты.

Определение
  • Table < (2%*buffer_cache) = _small_table_threshold is located into the middle point of LRU list when loaded into the buffer cache.
  • Table > (2%*buffer_cache) = _small_table_threshold is located into the cold end of the LRU list when loaded into the buffer cache.


По результатам тестов Льюиса для Oracle 10.2, проверяется содержимое буферного кеша (x$bh), количество touch и количество блоков для таблиц разных размеров:
  1. Для больших таблиц (свыше 10% кеша) touch не увеличивается, используется table scans (long)
  2. Для таблиц больше 25% буферного кеша при сканировании буферы переиспользуются
  3. Для таблиц меньше 10% буферного кеша touch увеличивается, причем первое сканирование таблицы не увеличивает touch (получается table scans (long)), последующие увеличивают (table scans (short))
  4. Для таблиц менее 2% touch count увеличивается каждый раз, используются table scans (short)
  5. Для 9-й и менее версий оракла поведение соответствует определению.

2011-03-16

Немного о лицензировании

Первая вьюха:
select * from v$license;

SESSIONS_MAX 0
SESSIONS_WARNING 0
SESSIONS_CURRENT 2
SESSIONS_HIGHWATER 7
USERS_MAX 0
CPU_COUNT_CURRENT 1
CPU_CORE_COUNT_CURRENT
CPU_SOCKET_COUNT_CURRENT
CPU_COUNT_HIGHWATER 1
CPU_CORE_COUNT_HIGHWATER
CPU_SOCKET_COUNT_HIGHWATER


Информация по использованию опций:
SELECT * FROM dba_feature_usage_statistics
Вьюха основана на таблицах wri$:
create or replace view dba_feature_usage_statistics as
select samp.dbid, fu.name, samp.version, detected_usages, total_samples,
decode(to_char(last_usage_date, 'MM/DD/YYYY, HH:MI:SS'),
NULL, 'FALSE',
to_char(last_sample_date, 'MM/DD/YYYY, HH:MI:SS'), 'TRUE',
'FALSE')
currently_used, first_usage_date, last_usage_date, aux_count,
feature_info, last_sample_date, last_sample_period,
sample_interval, mt.description
from wri$_dbu_usage_sample samp, wri$_dbu_feature_usage fu,
wri$_dbu_feature_metadata mt
where
samp.dbid = fu.dbid and
samp.version = fu.version and
fu.name = mt.name and
fu.name not like '_DBFUS_TEST%' and /* filter out test features */
bitand(mt.usg_det_method, 4) != 4 /* filter out disabled features */;


Пополняются они один раз в неделю (колонка sample_interval = 604800). Значение интервала берется из таблицы WRI$_DBU_USAGE_SAMPLE, API для изменения этого значения (кроме прямого UPDATE) найти не удалось.

Единственный пакет, который ссылается на эту таблицу: dbms_feature_usage_internal, который содержит 2 интересные процедуры:
EXEC dbms_feature_usage_internal.exec_db_usage_sampling(curr_date => SYSDATE) Заработало только после переподключения сессии, почему-то не обновляет в wri$_dbu_usage_sample колонку last_sample_date, но обновление количества использований после переподключения сессии происходит (до переподключения в трейсе вообще не было UPDATEов)
EXEC dbms_feature_usage_internal.sample_one_feature(feat_name => 'Automatic Workload Repository') - приводит к обновлению dba_feature_usage_statistics, причем дата последнего обновления проставляется в last_sample_date для всех опций (т.к. она одна и берется из таблицы wri$_dbu_usage_sample).

Что делают эти процедуры можно посмотреть, сняв трейс 10046.

2011-02-01

Как заставить работать lateral в oracle

ANSI SQL оператор lateral аналогичнен конструкции TABLE в Oracle.
Но просто так он не работает:
sps@v-pc-dev-3>SELECT *
2 FROM dual d1,
3 lateral (
4 SELECT * FROM dual d2 WHERE d2.dummy = d1.dummy
5 )
6 WHERE d1.dummy = 'X';
lateral (
*
ошибка в строке 3:
ORA-00933: SQL command not properly ended

Внимание на условие d2.dummy = d1.dummy внутри lateral.

Но
sps@v-pc-dev-3>alter session set events '22829 trace name context forever';

Сеанс изменен.

sps@v-pc-dev-3>SELECT *
2 FROM dual d1,
3 lateral (
4 SELECT * FROM dual d2 WHERE d2.dummy = d1.dummy
5 )
6 WHERE d1.dummy = 'X';

D D
- -
X X

1 строка выбрана.

2010-06-03

Скрипт для проверки привелегий

При изменении инсталляции и инсталляции из дампа привелегии можно проверить скриптом:
SELECT grantee "Кому", granted_role "Что", NULL "На что"
FROM Dba_Role_Privs
WHERE grantee LIKE 'SP%' OR grantee LIKE 'PN%'
OR granted_role LIKE 'SP%' OR granted_role LIKE 'PN%'
UNION ALL
SELECT grantee, PRIVILEGE, table_name
FROM Dba_Tab_Privs
WHERE grantee LIKE 'SP%' OR grantee LIKE 'PN%'
UNION ALL
SELECT grantee, PRIVILEGE, NULL
FROM dba_sys_Privs
WHERE grantee LIKE 'SP%' OR grantee LIKE 'PN%'
ORDER BY 1,2,3

2010-05-28

Список ролей, которые необходимо создать перед импортом

Импорт ругается на ошибки при разворачивании дампа? Пропускаем лог через скрипт:
$ grep " TO \"" specpr.log | sed s/'^.* TO "\(.*\)".*"$'/'CREATE ROLE \1;'/g | sort | uniq
и получаем список ролей, которые необходимо создать.

2010-04-30

Тайм менеджмент. Вольный пересказ книги Глеба Архангельского

Причины творческой лени

  • усталость и переутомнение
  • несоответсвие нашего "должен" нашему "хочу"
  • ощущение ненужности выполняемой в данный момент задачи
Россия воспитана на сказках, когда все появляется по "щучьему веленью". Но для достижения успеха нужен серьезный, долгий и упорный труд.

Как себя мотивировать на выполнение "нудных", больших задач?

Резать слонов на биштексы. Не стоит бояться и глобализировать большие задачи. Надо разделить их на мелкие и решать их постепенно, резать слона на бифштексы. Бифштексы должны быть измеримыми (мы можем управлять только тем, что можно измерить). Решать их можно в произвольном порядке (метод швейцарарского сыра, выгрызая дырки из большой задачи каждый день). Планировать и незамедлительно решать некоторое количество неприятных задач (съедать каждое утро по лягушке). Поощрять себя (хотя достижение результата это и так неплохая мотивация) за каждую небольшую победу. Маленькие победы можно фиксировать, например на графике, что дает дополнительную мотивацию.

Использовать "якорь" для быстрого включения в работу. Одним из самых простейших якорей является музыка. Нам песня работать и жить помогает.

Некоторым помогает работа в режиме дедлайна, который можно создавать искусственно.

Таблицы дел

Завести и повесить таблицу ежедневных дел. Выпонил дело -- ставишь галочку, не выполнил дело -- ставишь прочерк. За каждые пятнадцать галочек поощрение. По количеству прочерков видно, какие дела надо подтягивать.

Реактивный и проактивный подходы к жизни

Автор великолепно разжевывает идею Стивена Кови о реактивном и проактивном подходе к жизни.
Он постоянно плыл по течению, спотыкаясь о самого себя, постоянно придумывая оправдания своим неудачам, отказываясь принять на себя ответсвенность.
Люди ведут себя подобно ему, словно они сего лишь проходят мимо жизни, перебираясь из одного дня в другой. Не то, что бы у них не было желаний и мечтаний, как они добиваются успеха, но эти мечты сопровождаются многими оправданиями своего ничего неделания, основанных на убедительных доводах и они мгновенно преграждают им путь, как только такие люди начинают думать, что, возможно, - лишь возможно! - наступит день, когда они начнут исполнять эти желания.
 Но им всегда что-нибудь мешает - неудачное время года, срочный ремонт автомобиля или то, что они слишком устали вчера вечером. Так они говорят, но истина заключается в том, что единственным препятствием, стоящим на их пути, являются они сами…
Эта мысль приведена автором из Чака Норриса. Кто хочет ищет способы, кто не хочет - оправдания. Ох, как же часто (кажется), что на нас давят непреодолимые внешние обстоятельства: нет времени, нет денег, устал... А на самом деле это обычный реактивный подход к жизни -- плыть себе и плыть как гамно по течению. Тут уж надо действительно разобраться: нужно тебе это или не нужно. Цель это или мечта (а помечтать, как заметил автор, русский народ любит).

Родные и навязанные цели

Родными целями можно назвать всесторонне обдуманную, проанализированную, "выстраданную" цель. Например как открыть в городе первый медицинский центр. Или освоить новый язык программирования. В противоположность им есть цели навязанные: рекламой, родственниками, стереотипами, окружающей средой, моралью и этикой развращенного общества: я получаю лимон, у меня есть Ламборджини, 3 любовницы и квартира в центре Москвы. Задача человека: отсеять эту шелуху, найти свои истинны ценности.

Мемуарник. Призвание -> Миссия -> Цель

Продолжая тему о постановке глобальных целей жизни, поднятую Кови, Глеб предагает определить свои базовые ценности, на основе которых будут строится долгосрочные цели-маяки. Для этого каждый день записываем в мемуарник Главное Событие Дня, каждую недулю - Главное Событие Недели. Для каждого из этих событий определяем категорию, к которой оно относится, например: поговорил с другом (Друзья), навестил брата (Семья), погулял по историческим местам Москвы (путешествия, новизна ощущений, развитие). У каждого человека свой набор ценностей, важно определить "свои родные", ключевые ценности.

Приводится интересное определение: цель -- то что мы берем от жизни, завоевываем, миссия -- то что отдаем, приносим в этот мир. Для формирования своей миссии автор предлагает составить на себя эпитафию, что скажут потомки, после того, как Вы умрете. Миссию компании можно проверить аналогично.

От миссии переходим к призванию. Если миссию человек может поменять по своему усмотрению в течении своей жизни, то призвание уже на всю жизнь. Любой человек стремится к свободе, а призвание, как то от чего нельзя отказаться, нельзя бросить -- высшая степень несвободы. Но именно оно дает высшую степень осмысленности жизни, счастье.

Ключевые области жизни

Если собрать все задачи и попробовать повесить на них таги, то у занятых людей можно выделить по 5-10  основных тагов (ключевых областей жизни). В каждой из этих областей жизни необходимо иметь четкие цели, сами области долны быть приоритезированы между собой для соблюдения баланса времени между задачами из разных областей.

При достижении долгосрочных целей важно расставить приоритеты. Добиться успеха на работе, в спорте и стать отцом 3 детей вряд ли получится. Необходимо расставить приоритеты и выделить первоочередные цели. Сделать это можно например при помощи мемуарника (= набору ключевых ценностей). Сразу вспоминается Кови с главой про лидерство: Прежде чем взбираться по лестнице убедитесь, что она приставлена к правильной стене.

Карта ценностей

Конечной целью составления целей, ключевых ценностей, миссии, ключевых областей -- карта ценностей. По горизонтальной оси годы, повертикальной области жизни. Составляем примерный план что-где-когда мы хотим достичь. Пусть план будет неточный, но зато он будет.

SMART-цели

Цели должны быть SMART - от слов specific, measurable, achievable, realistic, time-bound - конкретные, измеримые, достижимые, реалистичные, привязанные к времени, например: в этом году получить сертификат OCP.

Планирование дня

Планы нужны для ситуаций, когда все меняется. Вы ведь не планируете чистку зубов, т.к. этот процесс понятен и предсказуем.
Задачи делятся на:
  • жесткие - привязанные ко времени (совещание в 12-00)
  • гибкие - можно делат ьв любое удобное время (слепить патч)
  • бюджетируемые - крупные задачи без конкретного времени исполнения (подготовить лекцию)
В силу того, что мои задачи пока все гибкие из планирования дня я выношу, что лучше иметь хоть какой-то план чем вообще никакого. В моем случае план - конвеер задач, которые решаются непрерывно.

Планирование по принципу День-Неделя-Год

Совсем положе на Планарий, с задачами на день, неделю и хаос. Ежедневно просматриваем задачи и переносим их из Года в Неделю и из Недели в месяц.

Экономия времени

Учитесь говорить НЕТ
Учитесь расчищать вашу жизнь от навязанных дел -- умейте говорить нет делам, которые не соответствуют вашим принципам и целям, делам которые вам не нравятся.
Стратегии отказа:
  1. Военная хитрость -- попросту солгать. Может открыться и отношения будут испорчены.
  2. Логическая аргументация -- не подходит для эмоциональных людей
  3. Отложить/замотать -- к сожалению многие путают надежду и обещание.
  4. Сделать желаемое непривлекательным
  5. Третий путь -- предложить альтернативу
К сожалению твердый отказ у нас нетрадиционен, считается что необходимо оправдываться, хитрить, лгать. Необходимо развививать в себе чувство свободы личности, право на отказ, устанавливать свой privacity, т.е. личное пространство.

Метод здорового пофигизма
Подумай: а нужно ли это выполнять вообще? Может все рассосется и надобность отпадет. Помни принцип ПВО: Не спеши выполнять -- отменят.

Покупка своего времени
Делегируйте свои задачи, задачи которые вам не нравятся, задачи которые отнимают слишком много времени и сил. Передать кому-то, равно как и купить услугу на стороне может выйти дешевле, чем делать все самому. Помни: трать невосполнимое время на Главное.

Принятие решений

Принимай решения используя как можно большее количество критериев (матрицу критериев). Наппример, пишем программу и есть 2 разных варианта ее написать. Критерии для выбора того или иного варианта:
  • Скорость работы
  • Просто кода
  • Скорость реализации
  • Простота тестирования
Каждому из критериев присваиваем вес и считаем, сколько балов набрало каждое из решений. Измеряй, что бы управлять

Круг влияния и кргу беспокойства

У Кови введено понятие "круг влияния" и "круг беспокойства". Обычно круг беспокойства гораздо шире круга влияния. Но зачем беспокоится и вообще знать о том, что не влияет на вашу жизнь и на что не можете повлиять вы сами. Фильтруйте новости и информацию, которую получаете. Количество информации в мире растет по экспоненте и за всем не угонишься. Какая нам разница до наводнения в Папуа и теракта в Сомали.

Творческая карточека

  1. Материализация мыслей. Мысль не записанная мысль потерянная.
  2. Записывать не только свои мысли, но и чужие. Пусть мысли сталкиваются из этого может родится что-то новое. Мысли по теме можно помечать тегами, соответствующим ключевым областям жизни.
  3. Регулярно просматривать эту картотеку

Организация работы на основании структурирования внимания

Сознание человека может работать только с одним объектом, предсознание с 5-9 объектами одновременно. Подсознание работает с бесконечным числом объектов. Рабочее пространство должно соотвествовать этой структуре: в центре один объект с которым работаем, в близи 5-9 близконеобходимых объекта, все остальное на перифирии. Если что-то помещается в область предсознания (становится близконеобходимым объектом) необходимо что-то удалить из этой области, что бы объект не потерял значимость.

Поглотители времени

Интереснейшая мысль, как бюрократия разбазаривает наше личное время. Мы проводим часы земли, что бы сэкономить сто ватт электроэнергии, почему не провести час без бюрократии, что бы сэкономить годы человеческого времени. Вот и сейчас, что бы поменять свои права я вынужден тратить целый рабочий день на этих уебков.
Основным методом борьбы с поглотителями времени является измерение -- ежедневный хронометрах на что уходит сколько времени (интересно, туалет учитывать:)). Подсчитываем, сколько времени тратится на поглотители и строим график. Самое интересное, что как только мы начинаем учитывать и отображать показатель будет сам стремится в лучшую сторону.

Что делать в транспорте
Помимо очевидных читайте, слушайте аудиокигу, отдыхайте, учитесь очень понравился кусок про думайте:
– Обдумывайте конкретный список вопросов. Участники тренингов часто говорят: «В транспорте я думаю». Не тешьте себя иллюзией. Если у вас нет списка конкретных вопросов к размышлению (или ваше думание не есть сознательная обработка только что пришедшей в голову идеи), то скорее всего, абстрактное думание - просто пережевывание одного и того же на холостых оборотах мозга, без смысла и пользы. Гораздо лучше иметь конкретный список вопросов к размышлению в транспорте, и еще - в ходе размышлений обязательно нужно делать пометки в блокноте, чтобы не потерять ценные идеи.

Проведение совещаний

  1. Определитесь с форматом совещания: мозговой штурм/планерка/стратегическое свещание
  2. Определить круг участников. Слишком много лишнего народу будет уметь и мешаться. Или тихо спать в углу мирно тратя свое рабочее время.
  3. Определить круг рассматриваемых вопросов
  4. Определить длительность совещания и следящего за временем.
  5. Организуйте обстановку и разошлите материалы в сжатой форме. Для того, что бы определить, что люди с материалами ознакомились, попросите прислать несколько решений по вопросам. Не приславших решение не приглашайте. Без дополнительных стимулов читать материалы вряд ли кто станет.
  6. Зафиксиуйте и разошлите результаты. Незафиксировнные результаты = отсутствию совещания.

Научите других экономить свое и наше время

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

Тайм-менеджмент в семейной жизни

  • "Мы вместе" не значит, что "мы делаем одно и то же"
  • У каждого должно быть время для себя (особенно у интравертов)
  • Принципы взаимоотношений должны проговариваться в явном виде. А еще лучше прописываться.

Тайм-менеджмент и дети

  1. Самомотивация. Не допускать промедление и откладывание задач.
  2. Таблица ежедневных дел
  3. Планирование хороших оценок. Уделение внимания отстающему предмету.

Факты о времени

  • Жизнь дается человеку один раз
  • Время это материал из которого соткана жизнь
  • Время и поступки человека в нем необратимы

Философия ТМ

Организация времени расположением дел и поступков в нем подобно организации пространства перемещением и расположением вещей. Существует 3 уровня организации времени:
  1. Как идти - эффективность - технологический
  2. Куда идти - стратегия - стратегичский
  3. Зачем идти - философия - мировозренческий
Все уровни взаимосвязаны и влияют один на другой. Вместе называется лестница тайм менеджмента.

Взаимозависимость уровней

Начиная заниматься тайм-менеджментом, задумываясь, как использовать время более эффективно, приходишь к вопросу о целях. Из множества целей выбираются наиглавнейшие, становится вопрос приоритетов, который перерастает в вопрос ценностей. Таким образом человек поднимается вверх по лестнице тайм-менеджмента.
Освоившись, установив свои ценности, расставив свои приоритеты начинаешь ставить долгосрочные (годовые) и более краткосрочные (недельные) цели. На ненужные, не соответствующие ценностям задачи не тратим время -- делегируем, покупаем или откладываем их в долгий ящик (метод трех гвоздей).

ТМ-идеалогия одной фразой

«Вдумчиво и осмысленно использовать невосполнимое время жизни в соответствии с осознанными личными ценностями и приоритетами».

Аксиомы ТМ

1. Человек свободен. Поступки могут зависить от начальных условий: ресурсы, наследственность. Однако ничто не определяет нашу жизнь на 100 процентов. Решающее значение имеет наш собственный выбор и наше желание что-то поменять. Не надо ныть и винить во всем окружение, государство, правительство (как это по-русски). Человек свободен изначально и во всем виноват только он сам. Если человек понял, что он свободен, а это чувство начинается внутри, то он может отсеять навязанную ему шелуху, штампы, как он должен жить и что он должен делать.
2. Ответственность. Человек отвечает за тот как он строит свою жизнь и тратит свое время. Цитата про проактивность:
«Амебой», а не «Человеком», я назову человека, неосмысленно и безответственно плывущего по течению, реагирующего на внешние воздействия, но не применяющего свою свободу к построению своей жизни и не берущего на себя ответственность за то, что с его жизнью и его временем происходит.
К сожалению, именно на постсоветском пространстве эта болезнь особенно сильна. Сколько наш человек может придумать причин, почему он не несет ответственности за то, что с ним происходит. Виноваты всегда правительство, президент, жидомасоны, олигархи, демократы, коммунисты, ЖЭК, работодатель и т.д. Знакомо?
3. Развитие. Время жизни - время развития, время совершенствования.

Тайм менеджент не только защита своего времени (время=деньги, позволять воровать свое время и чем не лучше, чем позволить украсть у тебя из кошелька, даже хуже, т.к. время не восполнимо), но и бережное отношение к времени других.

Не быть амебой поможет поставновка целей и определение ценностей.
Цели - самое простое для нас, мы творческая нация, мы умеем мечтать. Но дальше начинается этап тяжелого труда. Большинство жизнеописаний великих людей довольно-таки скучно читать. «Мы решили копать там, где никто еще не копал. Мы копали долго, все вокруг над нами смеялись. Потом сломалась лопата. Ее было сложно починить, но мы ее починили. Потом мы поняли, что копали не в ту сторону, а еще мы натерли мозоли до крови, а денег на пластырь не было, но мы все равно копали». Да, именно так - никаких чудес, никакой золотой рыбки, никакого «щучьего веления». Удача чаще приходит к тому, кто вкалывает, чем к тому, кто лежит на печи и ждет, когда же его жизнь изменится к лучшему.

Помни. Время невосполнимо.

PS: анекдот понравился: «Товарищи, товарищи, я без очереди!» - «Очередь для тех, кто без очереди, - в соседнее окошко!»

2010-04-29

Порядок функциональных предикатов в запросе

Как показано в этой замечательной статье, если у оптимизатора нет информации о функции (статистике), то порядок предикатов в WHERE условии соответствует написанному в запросе.

Наличие статистики можно определить по трейсу 10053, в котором содержаться такие строки
No default cost defined for function SOME_FUNCTION
No default selectivity defined for function SOME_FUNCTION

Связать статистику с функцией можно при помощи селективности по-умолчанию:
ASSOCIATE STATISTICS WITH FUNCTIONS quick_function DEFAULT SELECTIVITY 0.1;

Данная команда не очищает закешированные планы. Это можно сделать по хитрому, поменяв комментарий в используемой запросом таблице :)
Кроме селективности для функций можно задавать стоимость (CPU Cost, IO Cost, Net Cost)
ASSOCIATE STATISTICS WITH FUNCTIONS high_cpu_io DEFAULT COST (6747773, 210, 0);

Так же в статье описан Extensible Optimiser, представляющий собой объектный тип, возвращающий статистику по функции во время выполнения запроса.

2010-04-02

Порядок загрузки linux

После загрузки ядра читается файл /etc/inittab. В нем указывается уровень загрузки по умолчанию (уровень загрузки для большинства операционных систем свой).
id:3:initdefault:
TO KNOW: командой init 6 можно перезагрузить сервер
В /etc/inittab указываются скрипты или папки, которые запускаются при загрузке соответствующего уровня:
l3:3:wait:/etc/rc.d/rc 3
Для того, что бы добавить что-то в автозагрузку необходимо:
1. Написать скрипт и поместить его в /etc/init.d, дать ему необходимые привелегии
2. Поместить его через symlink в /etc/rc.d на необходимый уровень и на необходимое действие.
Если в заголовке скрипта прописано
# chkconfig: 35 99 10
# description: Description here

то можно воспользоваться командой /sbin/chkconfig --add ИМЯ_СКРИПТА, которая добавит сервис автоматически.
  • 35 -- на уровнях 3 и 5 сервис будет запускаться, на остальных останавливаться.
  • 99 -- сервис будет запукаться где-то в конце
  • 10 -- сервис будет останавливаться одним из первых.

В результате, для файла dbora, получим сформированные симлинки:
/etc/rc.d/rc0.d/K10dbora
/etc/rc.d/rc1.d/K10dbora
/etc/rc.d/rc2.d/K10dbora
/etc/rc.d/rc3.d/S99dbora
/etc/rc.d/rc4.d/K10dbora
/etc/rc.d/rc5.d/S99dbora
/etc/rc.d/rc6.d/K10dbora
К -- запуск для останова сервиса, dbora stop, S -- запуск сервиса dbora start. Скрипты выполняются по порядку нумерации, если хотим, что бы скрипт выполнился в начале, присваем ему номер поменьше.

Также можно поместить вызов скрипта в /etc/rc.d/rc.local (или /etc/rc.local, что одно и то же). Скрипт выполняется один раз, до логина. Скрипт выполняется после всех инициализационных скриптов, но до окна логина.
Некоторые дистрибутивы линукса могут не запускать этот файл.

2010-04-01

Файлы инициализации в Linux

Типы запуска командной оболочки


Interctive login shell запускается, когда пользователь входит в систему посредством ввода логина и пароля (выполняется скрипт /bin/login и введенный пароль проверяется посредством /etc/passwd).

Interactive non login shell запускается, когда пользователь запускает оболочку без ввода пароля:
* [prompt]/bin/bash --
* su username (без минуса копирует родительское окружение, с минусом не копирует)
* xterm, console из графического интерфейса

Файлы, выполняющиеся при запуске командной оболочки


  • /etc/profile -- запускается при любом входе в любую оболочку
  • ~/.bashrc -- вход без логина (например, родительская оболочка установлена в ksh, в ней мы вызываем bash командой. Если мы хотим инициализировать переменные, то делаем это в этом файле).
  • ~/.bash_profile -- вход с логином
  • /etc/bashrc -- обычно существует и вызывается из ~/.bashrc (вызов пишется ручками, см. ниже)
  • /etc/profile.d/*.sh -- вызывается из /etc/profile (вызов пишется ручками, см. ниже)


Взаимосвязи между файлами


На примере типичной конфигурации
1. ~/.bashrc вызывается из ~/.bash_profile. Если создавался пользователем самостоятельно, то этого важного вызова может и не быть
if [ -f ~/.bashrc ]; then
. ~/.bashrc
fi

2. /etc/bashrc из ~/.bashrc
if [ -f /etc/bashrc ]; then
. /etc/bashrc
fi

3. /etc/profile.d/*.sh из /etc/profile
for i in /etc/profile.d/*.sh ; do
if [ -r "$i" ]; then
if [ "$PS1" ]; then
. $i
else
. $i >/dev/null 2>&1
fi
fi
done


4. /etc/profile.d/*.sh из /etc/bashrc
# Only display echos from profile.d scripts if we are no login shell
# and interactive - otherwise just process them to set envvars
for i in /etc/profile.d/*.sh; do
if [ -r "$i" ]; then
if [ "$PS1" ]; then
. $i
else
. $i >/dev/null 2>&1
fi
fi
done


Тестирование запуска оболочек



Добавим в указанные выше файлы /etc/profile, ~/.bash_profile, ~/.bashrc, /etc/bashrc, /etc/profile.d/testbash.sh строчку с заполнением название скрипта в лог. Строка добавлена в конец файла, так что при вызове другого файла сначала появляется запись о другом файле, потом о текущем

При обычном входе с логином паролем


script name: /etc/profile.d/testbash.sh
script name: /etc/profile
script name: /etc/bashrc
script name: roots .bashrc
script name: roots .bash_profile


su - Запуск без сохранения окружения


script name: /etc/profile.d/testbash.sh
script name: /etc/profile
script name: /etc/bashrc
script name: roots .bashrc
script name: roots .bash_profile


su Запуск с сохранением окружения


script name: /etc/profile.d/testbash.sh
script name: /etc/bashrc
script name: roots .bashrc


Запуск скрипта


#!/bin/bash
echo Hello
ПУСТО

Запуск другой оболочки /bin/ksh


ПУСТО

Запуск /bin/bash


script name: /etc/profile.d/testbash.sh
script name: /etc/bashrc
script name: oracles .bashrc


Выводы


Лучше всего окружение настраивать в .bashrc, убедившись, что в .bash_profile есть ссылка на .bashrc
if [ -f ~/.bashrc ]; then
. ~/.bashrc
fi


За более подробной информацией: info bash
По материалам статьи http://www.linuxfromscratch.org/blfs/view/6.3/postlfs/profile.html