Alta disponibilidade com Debian Lenny + Heartbeat + DRBD8 + OCFS2 + MONIT + LVS

Neste artigo trataremos de como implementar alta disponibilidade tendo como exemplo um servidor web. Dá um pouco de trabalho, mas quando pronto e você testa a sua alta disponibilidade e vê tudo funcionando como você queria, dá um ar de satisfação tremendo.

[ Hits: 132.648 ]

Por: Douglas Q. dos Santos em 21/03/2010 | Blog: http://wiki.douglasqsantos.com.br


Preparação do ambiente



Antes de começarmos a efetuar a nossa implementação vamos seguir alguns passos.

Primeiro ajustar os repositórios, pois não adianta tentar achar todos os pacotes que vamos precisar no DVD de instalação que não vai ter.

Então faça um backup do arquivo de repositório caso precise depois.

Efetuando backup do arquivo do apt:

# mv /etc/apt/sources.list /etc/apt/sources.list.orig

Editando o arquivo do apt com os seguintes repositórios:

# vi /etc/apt/sources.list

# Repositório oficial Brasil
deb ftp://ftp.br.debian.org/debian lenny main contrib non-free
deb-src ftp://ftp.br.debian.org/debian lenny main contrib non-free

#Se quiser utilizar os repositórios USA descomente a linha
deb ftp://ftp.us.debian.org/debian lenny main contrib non-free
deb-src ftp://ftp.us.debian.org/debian lenny main contrib non-free

# Repositório de atualizações frequentes
deb http://volatile.debian.org/debian-volatile lenny/volatile main contrib non-free
deb-src http://volatile.debian.org/debian-volatile lenny/volatile main contrib non-free

# Repositório de atualizações de segurança
deb http://security.debian.org/ lenny/updates main contrib non-free
deb-src http://security.debian.org/ lenny/updates main contrib non-free

# Repositório de atualizações propostas
deb ftp://ftp.br.debian.org/debian lenny-proposed-updates main contrib non-free
deb-src ftp://ftp.br.debian.org/debian lenny-proposed-updates main contrib non-free

Atualizando as chaves de repositório (KEYRINGS):

# aptitude -y install debian-backports-keyring
# gpg --keyserver wwwkeys.pgp.net --recv-keys 1F41B907
# apt-key add ~root/.gnupg/pubring.gpg


Vamos instalar os pacotes de pré-requisitos para não termos problemas com falta de algum aplicativo. Aqui eu estou instalando o vim, mas se não quiser utilizar este editor use o seu editor preferido.

# aptitude -y install vim vim-scripts ctags vim-doc
# aptitude -y install zip unzip rar p7zip bzip2
# aptitude -y install less links telnet pciutils locate
# aptitude -y install openssh-server sysv-rc-conf
# aptitude -y install htop nmap tcpdump rsync
# aptitude -y install build-essential libncurses5-dev


Vamos ajustar a hora:

# apt-get -y remove --purge tz-brasil
# aptitude -y install ntpdate tz-brasil
# ntpdate -u ntp.usp.br
# hwclock --systohc


Vamos atualizar todo o sistema agora, pois precisamos ter uma base atualizada para termos uma boa compatibilidade de aplicativos, caso você não queira efetuar este processo, fique ciente que algo pode dar errado, "LEI DE MURPH" é muito bem empregada em alta disponibilidade.

# aptitude -y dist-upgrade

Página anterior     Próxima página

Páginas do artigo
   1. Um pouco de história
   2. Nosso ambiente de implementação
   3. Preparação do ambiente
   4. Instalação e configuração do Heartbeat
   5. Gerenciando o Heartbeat com Haclient
   6. Instalação e configuração do DRBD8 e OCFS2
   7. LVS
   8. Instalação e configuração do Monit
Outros artigos deste autor

Apache em chroot + MySQL + PHP + mod_security + mod_evasive + vsftpd + Fail2ban + Debian Squeeze

Um pouco sobre IPtables

Debian + Postfix + MySQL + PostfixAdmin + MailScanner + Webmail + Quotas

Servidor Jabber com Openfire + MySQL + Debian Lenny

IDS com Snort + Guardian + Debian Lenny

Leitura recomendada

Post-la - Gerador de relatórios para o Postfix

Instalação do Zextras Suite para o Zimbra

Integrando o Amavisd-new, SpamAssassin e ClamAV com o Postfix no SuSE 9.3

Importando e-mails do MS Outlook para o Evolution ou Kmail

Configurando servidor IMAP

  
Comentários
[1] Comentário enviado por luizvieira em 21/03/2010 - 09:25h

Muito bom, essa semana mesmo preciso implementar um ambiente desses e talvez seu artigo possa me ajudar.
Parabéns!
[ ]'s
Luiz

[2] Comentário enviado por leandrojpg em 22/03/2010 - 09:04h

É, podem seguir linha a linha desse artigo que funciona, implantei aqui no meu trabalho e foi total sucesso, o Douglas fez um excelente trabalho.
muito obrigado.!!!!

[3] Comentário enviado por manoserpa em 22/03/2010 - 10:44h

Vou fazer meu TCC sobre cluster, esse artigo será bastante útil e vou usar como referência no meu trabalho.

Parabéns Douglas, e obrigado pelas dicas que você já meu deu até hoje.

Um abraço.

[4] Comentário enviado por douglas_dksh em 22/03/2010 - 13:25h

Obrigado pelos comentários.


Espero continuar contribuindo sempre.


Douglas.

[5] Comentário enviado por lemurbr em 21/04/2010 - 10:48h

Douglas,

Parabéns pelo excelente artigo, vc foi muito didático e me ajudou muito na implantação de uma solução similar em um cliente.
Seu artigo esta muito bem escrito e direto.
Estou tentando adaptar essa solução para um servidor samba com controlador de dominio o processo está de vento em popa.
Mas ficaram três dúvidas :
Primeiro - Utilizo o Debian Lenny atualizado, mas o parâmetro que foi indicado no FSTAB ( _netdev ) não esta seno reconhecino na inicialização da máquina, consequentemente ele não monta o filesystem OCFS2 automaticamente.
Segundo - No início do seu artigo deu a entender que precisava-se de 2 placas de rede em cada máquina mas ao implementar o mesmo não encontrei referência alguma da configuração dessa segunda placa.
Terceiro com relação ao LVS achei a idéia muito boa mas é realmente necessário a adição de uma terceira máquina no serviço ? Poderia-se colocar o LVS em uma das máquinas do cluster?

Mais uma vez parabéns pelo excelente artigo continue assim nossa comunidade só tem a ganhar ....

Viva a Liberdade
Viva o Linux

Uma abraço

Luiz Xavier .:

[6] Comentário enviado por lemurbr em 23/04/2010 - 16:10h

Boa Tarde Douglas !!!


Das minhas dúvidas eu já consegui resolver uma :
a linha do FSTAB referente a montagem do OCFS2 está errada o correto segue abaixo :

/dev/drbd1 /ocfs2 ocfs2 _netdev,defaults 0 0

Espero ter ajudado ;)

Atenciosamente

Luiz Xavier.:

Viva a Liberdade !!!
Viva o Linux !!!

[7] Comentário enviado por lemurbr em 28/04/2010 - 17:30h

Boa Tarde a todos ....

Mais uma vez gostaria de deixar minhas impressões com as pessoas que verem esse tópico.

Nosso colaborador Douglas está de parabéns .

Segui seu tutorial e fiz alguns ajustes e hoje sou um feliz próprietário de um cluster total rodanda Samba PDC, Squid Autenticado e OpenVpn.


Parabéns mais uma vez

Continue sempre assim ...

Viva a Liberdade !!!
Viva o Linux !!!!

Luiz Xavier .:

[8] Comentário enviado por fermguft em 30/04/2010 - 14:58h

Olá...

Primeiramente parabéns pelo artigo. Será de grande valia!!!

Tenho um problema: na hora de executar o Heartbeat em modo gráfico (heartbeat-2-gui) dá erro e nao abre. Tentei instalar em outra máquina e utilizar o putty e colocar o comando, mas ele nem abre. Se eu digitar o comando, da erro também. Alguem passou por isso, ou sabe como ontornar isso?

Situação:
Instalação em duas máquinas Debian/Lenny atualizadas, somente modo texto.

Erro:

debian1:~# /usr/lib/heartbeat-gui/haclient.py &
[1] 2372
debian1:~# /var/lib/python-support/python2.5/gtk-2.0/gtk/__init__.py:72: GtkWarning: could not open display
warnings.warn(str(e), _gtk.Warning)
/usr/lib/heartbeat-gui/haclient.py:1964: Warning: invalid (NULL) pointer instance
win_widget = gtk.Window()
/usr/lib/heartbeat-gui/haclient.py:1964: Warning: g_signal_connect_data: assertion `G_TYPE_CHECK_INSTANCE (instance)' failed
win_widget = gtk.Window()
/usr/lib/heartbeat-gui/haclient.py:2077: Warning: invalid (NULL) pointer instance
menubar = uimanager.get_widget('/menubar')
/usr/lib/heartbeat-gui/haclient.py:2077: Warning: g_signal_connect_data: assertion `G_TYPE_CHECK_INSTANCE (instance)' failed
menubar = uimanager.get_widget('/menubar')
/usr/lib/heartbeat-gui/haclient.py:2077: GtkWarning: gtk_settings_get_for_screen: assertion `GDK_IS_SCREEN (screen)' failed
menubar = uimanager.get_widget('/menubar')
/usr/lib/heartbeat-gui/haclient.py:2077: Warning: g_object_get: assertion `G_IS_OBJECT (object)' failed
menubar = uimanager.get_widget('/menubar')
/usr/lib/heartbeat-gui/haclient.py:2077: Warning: value "TRUE" of type `gboolean' is invalid or out of range for property `visible' of type `gboolean'
menubar = uimanager.get_widget('/menubar')
/usr/lib/heartbeat-gui/haclient.py:2084: Warning: invalid (NULL) pointer instance
glade = gtk.glade.XML(UI_FILE, "mainwin_main", "haclient")
/usr/lib/heartbeat-gui/haclient.py:2084: Warning: g_signal_connect_data: assertion `G_TYPE_CHECK_INSTANCE (instance)' failed
glade = gtk.glade.XML(UI_FILE, "mainwin_main", "haclient")
/usr/lib/heartbeat-gui/haclient.py:2084: GtkWarning: gtk_settings_get_for_screen: assertion `GDK_IS_SCREEN (screen)' failed
glade = gtk.glade.XML(UI_FILE, "mainwin_main", "haclient")
/usr/lib/heartbeat-gui/haclient.py:2092: GtkWarning: Screen for GtkWindow not set; you must always set
a screen for a GtkWindow before using the window
win_widget.show_all()
/usr/lib/heartbeat-gui/haclient.py:2092: GtkWarning: gtk_settings_get_for_screen: assertion `GDK_IS_SCREEN (screen)' failed
win_widget.show_all()
/usr/lib/heartbeat-gui/haclient.py:2092: Warning: g_object_get: assertion `G_IS_OBJECT (object)' failed
win_widget.show_all()
/usr/lib/heartbeat-gui/haclient.py:2092: GtkWarning: gdk_pango_context_get_for_screen: assertion `GDK_IS_SCREEN (screen)' failed
win_widget.show_all()
/usr/lib/heartbeat-gui/haclient.py:2092: PangoWarning: pango_context_set_font_description: assertion `context != NULL' failed
win_widget.show_all()
/usr/lib/heartbeat-gui/haclient.py:2092: PangoWarning: pango_context_set_base_dir: assertion `context != NULL' failed
win_widget.show_all()
/usr/lib/heartbeat-gui/haclient.py:2092: PangoWarning: pango_context_set_language: assertion `context != NULL' failed
win_widget.show_all()
/usr/lib/heartbeat-gui/haclient.py:2092: PangoWarning: pango_layout_new: assertion `context != NULL' failed
win_widget.show_all()
/usr/lib/heartbeat-gui/haclient.py:2092: PangoWarning: pango_layout_set_text: assertion `layout != NULL' failed
win_widget.show_all()
/usr/lib/heartbeat-gui/haclient.py:2092: PangoWarning: pango_layout_set_attributes: assertion `layout != NULL' failed
win_widget.show_all()
/usr/lib/heartbeat-gui/haclient.py:2092: PangoWarning: pango_layout_set_alignment: assertion `layout != NULL' failed
win_widget.show_all()
/usr/lib/heartbeat-gui/haclient.py:2092: PangoWarning: pango_layout_set_ellipsize: assertion `PANGO_IS_LAYOUT (layout)' failed
win_widget.show_all()
/usr/lib/heartbeat-gui/haclient.py:2092: PangoWarning: pango_layout_set_single_paragraph_mode: assertion `PANGO_IS_LAYOUT (layout)' failed
win_widget.show_all()
/usr/lib/heartbeat-gui/haclient.py:2092: PangoWarning: pango_layout_set_width: assertion `layout != NULL' failed
win_widget.show_all()
/usr/lib/heartbeat-gui/haclient.py:2092: PangoWarning: pango_layout_get_extents: assertion `layout != NULL' failed
win_widget.show_all()
/usr/lib/heartbeat-gui/haclient.py:2092: PangoWarning: pango_layout_get_pixel_extents: assertion `PANGO_IS_LAYOUT (layout)' failed
win_widget.show_all()
/usr/lib/heartbeat-gui/haclient.py:2092: Warning: g_object_unref: assertion `G_IS_OBJECT (object)' failed
win_widget.show_all()
/usr/lib/heartbeat-gui/haclient.py:2092: GtkWarning: gtk_icon_size_lookup_for_settings: assertion `GTK_IS_SETTINGS (settings)' failed
win_widget.show_all()
/usr/lib/heartbeat-gui/haclient.py:2092: GtkWarning: /build/buildd-gtk+2.0_2.12.12-1~lenny2-i386-2RfKoO/gtk+2.0-2.12.12/gtk/gtkstyle.c:2123: invalid icon size '3'
win_widget.show_all()
/usr/lib/heartbeat-gui/haclient.py:2092: GtkWarning: gtk_style_render_icon: assertion `pixbuf != NULL' failed
win_widget.show_all()
/usr/lib/heartbeat-gui/haclient.py:2092: GtkWarning: Failed to render icon
win_widget.show_all()
/usr/lib/heartbeat-gui/haclient.py:2092: Warning: g_object_ref: assertion `G_IS_OBJECT (object)' failed
win_widget.show_all()
/usr/lib/heartbeat-gui/haclient.py:2092: PangoWarning: pango_context_get_language: assertion `context != NULL' failed
win_widget.show_all()
/usr/lib/heartbeat-gui/haclient.py:2092: PangoWarning: pango_context_get_metrics: assertion `PANGO_IS_CONTEXT (context)' failed
win_widget.show_all()
/usr/lib/heartbeat-gui/haclient.py:2092: PangoWarning: pango_font_metrics_get_approximate_char_width: assertion `metrics != NULL' failed
win_widget.show_all()
/usr/lib/heartbeat-gui/haclient.py:2092: PangoWarning: pango_layout_get_context: assertion `layout != NULL' failed
win_widget.show_all()
/usr/lib/heartbeat-gui/haclient.py:2092: PangoWarning: pango_font_metrics_get_approximate_digit_width: assertion `metrics != NULL' failed
win_widget.show_all()
/usr/lib/heartbeat-gui/haclient.py:2092: PangoWarning: pango_font_metrics_get_ascent: assertion `metrics != NULL' failed
win_widget.show_all()
/usr/lib/heartbeat-gui/haclient.py:2092: PangoWarning: pango_font_metrics_get_descent: assertion `metrics != NULL' failed
win_widget.show_all()
/usr/lib/heartbeat-gui/haclient.py:2092: GtkWarning: gdk_screen_get_default_colormap: assertion `GDK_IS_SCREEN (screen)' failed
win_widget.show_all()
/usr/lib/heartbeat-gui/haclient.py:2092: GtkWarning: gdk_colormap_get_visual: assertion `GDK_IS_COLORMAP (colormap)' failed
win_widget.show_all()
/usr/lib/heartbeat-gui/haclient.py:2092: GtkWarning: gdk_screen_get_root_window: assertion `GDK_IS_SCREEN (screen)' failed
win_widget.show_all()
/usr/lib/heartbeat-gui/haclient.py:2092: GtkWarning: gdk_window_new: assertion `GDK_IS_WINDOW (parent)' failed
win_widget.show_all()
/usr/lib/heartbeat-gui/haclient.py:2092: GtkWarning: gdk_window_enable_synchronized_configure: assertion `GDK_IS_WINDOW (window)' failed
win_widget.show_all()
/usr/lib/heartbeat-gui/haclient.py:2092: GtkWarning: gdk_window_set_user_data: assertion `window != NULL' failed
win_widget.show_all()
/usr/lib/heartbeat-gui/haclient.py:2092: GtkWarning: gtk_style_attach: assertion `window != NULL' failed
win_widget.show_all()
/usr/lib/heartbeat-gui/haclient.py:2092: GtkWarning: gtk_style_set_background: assertion `GTK_IS_STYLE (style)' failed
win_widget.show_all()
/usr/lib/heartbeat-gui/haclient.py:2092: GtkWarning: gtk_paint_flat_box: assertion `GTK_IS_STYLE (style)' failed
win_widget.show_all()
/usr/lib/heartbeat-gui/haclient.py:2092: GtkWarning: gdk_window_set_accept_focus: assertion `GDK_IS_WINDOW (window)' failed
win_widget.show_all()
/usr/lib/heartbeat-gui/haclient.py:2092: GtkWarning: gdk_window_set_focus_on_map: assertion `GDK_IS_WINDOW (window)' failed
win_widget.show_all()
/usr/lib/heartbeat-gui/haclient.py:2092: GtkWarning: gdk_window_set_modal_hint: assertion `GDK_IS_WINDOW (window)' failed
win_widget.show_all()
/usr/lib/heartbeat-gui/haclient.py:2092: GtkWarning: gtk_window_realize_icon: assertion `widget->window != NULL' failed
win_widget.show_all()
/usr/lib/heartbeat-gui/haclient.py:2092: GtkWarning: gdk_window_set_geometry_hints: assertion `GDK_IS_WINDOW (window)' failed
win_widget.show_all()
/usr/lib/heartbeat-gui/haclient.py:2092: GtkWarning: gdk_window_invalidate_rect: assertion `window != NULL' failed
win_widget.show_all()
/usr/lib/heartbeat-gui/haclient.py:2092: GtkWarning: gdk_window_show: assertion `GDK_IS_WINDOW (window)' failed
win_widget.show_all()
/usr/lib/heartbeat-gui/haclient.py:2092: GtkWarning: gdk_window_get_events: assertion `GDK_IS_WINDOW (window)' failed
win_widget.show_all()
/usr/lib/heartbeat-gui/haclient.py:2092: GtkWarning: gdk_window_set_events: assertion `GDK_IS_WINDOW (window)' failed
win_widget.show_all()
/usr/lib/heartbeat-gui/haclient.py:2092: GtkWarning: gdk_screen_get_display: assertion `GDK_IS_SCREEN (screen)' failed
win_widget.show_all()
/usr/lib/heartbeat-gui/haclient.py:2092: GtkWarning: gdk_cursor_new_for_display: assertion `GDK_IS_DISPLAY (display)' failed
win_widget.show_all()
/usr/lib/heartbeat-gui/haclient.py:2092: GtkWarning: gdk_cursor_unref: assertion `cursor != NULL' failed
win_widget.show_all()
/usr/lib/heartbeat-gui/haclient.py:2092: GtkWarning: gdk_window_set_back_pixmap: assertion `GDK_IS_WINDOW (window)' failed
win_widget.show_all()
/usr/lib/heartbeat-gui/haclient.py:2092: GtkWarning: gdk_drawable_get_colormap: assertion `GDK_IS_DRAWABLE (drawable)' failed
win_widget.show_all()
/usr/lib/heartbeat-gui/haclient.py:2092: GtkWarning: gdk_window_set_background: assertion `GDK_IS_WINDOW (window)' failed
win_widget.show_all()


[9] Comentário enviado por douglas_dksh em 03/05/2010 - 08:59h

Bom dia.

Cara pela sua situação abaixo.
Situação:
Instalação em duas máquinas Debian/Lenny atualizadas, somente modo texto.

Não tem como você executar o haclient.

/usr/lib/heartbeat-gui/haclient.py &

para você poder exportar a tela eu comentei no tutorial que precisa de uma maquina com modo gráfico.

e dava para fazer a exportação da tela do haclient.py via putty em modo grafico.

nem precisa ser a que tenha o servidor mais pelo meno um cliente pois a tela que vc esta querendo exportar é feita em python e necessita de algumas bibliotecas de modo grafico X.


para resolver o seu problema instale uma maquina com o modo grafico so para voce gerenciar o seu cluster e deixe os seus server somente com o modo texto para não ficar enchendo o seu server de aplicativos e bibliotecas X.


Douglas.

[10] Comentário enviado por lanzelotti em 06/08/2010 - 10:41h

Bom dia Douglas,

Já tinha o heartbeat instalado nos servidores(Debian 5), mas com a versão 1, instalei o heartbeat-gui nos servidores (locais) e usei o comando "/usr/lib/heartbeat-gui/haclient.py &".
Acesso os servidores com o ssh com X11 para usar a interface grafica da minha maquina local:
#ssh servidor -XY
Abri o Haclient normalmente:
Server 127.0.0.1
User Name hacluster
Password: em branco

Utilizo a senha que cadastrei mas não consigo conectar no servidor, tentei a conexão com o IP LAN do servidor mas gera o mesmo erro.
Tenho que especificar alguma porta?
Sabe o que pode estar ocorrendo?

Obs.: Não tenho firewall habilitado neste servidor e adicionei o user hacluster no grupo haclient(encontrei em um forum)

Obrigado e parabens!

[11] Comentário enviado por douglas_dksh em 06/08/2010 - 11:29h

Bom dia caro colega.

acho que vc esqueceu disso aqui.

Como na instalação do Heartbeat ele não pediu senha para o hacluster, temos que inserir uma para podemos conectar no Heartbeat.

# passwd hacluster

dai vc informa a senha e loga o hacliet.


Douglas

[12] Comentário enviado por joelmp em 26/09/2010 - 23:32h

Boa noite a todos

Agradeço o artigo, está me ajudando bastante.

Porem ainda tenho um problema com o heartbeat.
Quando o host1 e host2 estão operando não consigo acessar o apache na rede, porem quando coloco qualquer um deles em standby o serviço funciona.
alguem pode me dar uma dica?

[13] Comentário enviado por joelmp em 26/09/2010 - 23:43h

ops!

Já resolvi, era apenas um location para o mesmo serviço, ou seja, por engano setei um outro location qualquer com apache tbm, ai duplicou o serviço.

[14] Comentário enviado por doomk em 03/11/2010 - 15:16h

Tutorial simplesmente perfeito.


Está de parabéns.

[15] Comentário enviado por rodrigom em 17/05/2011 - 16:56h

Pessoal, estava seguindo esse tutorial, mas ai surgiu uma dúvida, onde gero essa senha ?


# vim /etc/ha.d/authkeys

# /etc/ha.d/authkeys

#Definir qual o método de autenticação.
auth 3

#Métodos de autenticação disponíveis
1 crc <--------------------------------------------------------------------
2 sha1 senha <----------------------------------------------------------
3 md5 senha <----------------------------------------------------------


Muito obrigado a todos, bom dia.

[16] Comentário enviado por felipeogutierrez em 20/11/2012 - 15:41h

Olá Douglas,

O heartbeat só funciona com cabo crossover ligando os nodos?

Obrigado,
Felipe

[17] Comentário enviado por douglas_dksh em 20/11/2012 - 16:09h

Boa tarde.

Não, pode ser utilizado um cabo padrão de rede, o heartbeat somente vai garantir que um endereço ip seja compartilhado entre os servidores, ou vai monitorar um determinado serviço ou partição, mas o servidor pode ser montado como qualquer outro.

[18] Comentário enviado por fernandofrauches em 04/06/2013 - 18:03h

Boa noite a todos.

Fui seguindo o tutorial passo a passo porem adaptando ele para minha situação. Estou utilizando ja o debian wheezy, e não consigo instalar o heartbeat-gui....
Busco ele no apt-get e ele não encontra....o heartbeat instalado é a versão 3

Obrigado.

[19] Comentário enviado por douglas_dksh em 06/06/2013 - 10:04h

E ai fernando o que acontece é o seguinte o projeto do heartbeat e do corosync forão separados e foram descontinuadas algumas features.

da uma olhada nesse link aqui http://www.douglas.wiki.br/doku.php?id=corosync_pacemaker_lcmc_no_debian_squeeze

aqui eu fiz a implementação com o novo modelo a implementação do squeeze e do wheezy é para ser a mesma.


Contribuir com comentário




Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts