Category Archives: Windows

AWS – VPN Server

Existem vários motivos para você querer rotear sua saída de internet por outro local ao invés do seu ISP de costume, privacidade? segurança? acesso a outros conteúdos de mídia?

O motivo em si é irrelevante, hoje contamos com diversos serviços de VPN pagos e gratuitos muito bons por aí, mas da pra confiar neles? uma VPN é basicamente um contrato de mão dupla, você confia em uma ponta enquanto a outra ponta confia em você, é estabelecido um canal de criptografia entre essas duas pontas e os dados podem ou não ser roteados através desse canal, em uma visão simplista uma análise de tráfego ou scan de rede pode partir de uma das pontas para “analisar” o que encontra-se do outro lado, por isso, mesmo uma VPN meia-boca costuma ter firewall restringindo quem e da onde pode vir o tráfego, mas em dispositivos de celular isso é quase impossível.

Claro que existem serviços honestos de VPN por aí, pagos ou gratuitos, mas por que ariscar se você pode montar um para você,,, e de graça,,,

Pra começar é simples, crie uma conta na AWS.

Depois vamos usar o serviço de Marketplace:

Procure por OpenVPN Access Server

Escolha a opção de Continue to Subscribe

Aceite os termos

Muitos termos

é só esperar para ele ativar o serviço na sua conta

Basicamente terminada a subscrição agora vamos iniciar uma máquina EC2 com o OpenVPN, escolha o local onde você vai hospedar a máquina EC2, basicamente qualquer lugar do mundo dentro da nuvem da AWS serve.

eu disse que era grátis? foi mesmo,,, você tem que alterar o tipo de máquina que vai ser usada para hospedar o OpenVPN para o modelo t2.micro

nessa parte onde você troca a máquina.

Aqui vem um detalhe, esse ambiente é grátis por 1 ano, se você já usou esse serviço de EC2 da AWS alguma vez e não aparecer a que vai ser grátis então chegou até aqui a toa, eles vão te cobrar, mas cabaçada sua de não prestar atenção nos termos de uso dos serviços deles…

VPC e Subnet a sua escolha, o que importa são as regras de firewall e o IP valido que vai ser criado para a máquina.

Como você está criado a máquina através de um template, ele já vem com um conjunto de regras pré definidas.

Essa parte é importante, salve a chave para que você tenha acesso a essa máquina através de SSH.

Basicamente após clicar em “Launch” a AWS vai criar a máquina, na região, com regras de firewall e o OpenVPN para você.

Mas não acabou por aqui, afinal, você vai querer acessar essa VPN.

Para acessar essa VPN antes você vai precisar configurar ela, nada tão complicado,,, apenas preste atenção nos detalhes, eles são a grande diferença

Após a máquina iniciar, você terá um endereço de IP válido e uma entrada de DNS. Se você não esqueceu de liberar o seu IP lá na regra de firewall você deve conseguir acessar esse servidor.

Antes de sair tentando acessar pelo Browser e configurar as coisas, você precisa logar no servidor e aceitar aqueles contratos, que como TODOS fazemos lemos até o fim um a um,,,, um a um,,,

Para acessar o servidor não precisa de nenhuma ferramenta especial (caso você esteja usando pelo menos o Windows 10), nos Linux e Mac’s da vida o ssh vem por padrão, no Windows 10 pra cima também, se você está usando alguma coisa mais antiga, procura algum cliente de SSH.

Para acessar esse novo servidor você vai abrir o prompt/terminal/posh o raio que quiser e basicamente digitar:

ssh -i "aquele_arquivo_de_chave" ec2user@IP_ou_FQDN
se não der certo tenta como root mesmo
ssh -i "aquele_arquivo_de_chave" root@IP_ou_FQDN

Se tudo deu certo, deve aparecer a licença, leia com cuidado, tudinho, tintim por tintim,,, e se achar que está tudo bem aceita a licença.

Na primeira vez que você faz login no Servidor de Acesso, um assistente de configuração é executado para permitir que você configure os parâmetros de inicialização antes de poder acessar a interface web administrativa. Neste assistente, você especifica alguns detalhes da rede e define um usuário administrador.

Se você optar por usar o usuário openvpn padrão como usuário administrador, certifique-se de definir uma senha para ele antes de acessar a interface web de administração. Para definir uma senha, use o seguinte comando shell:

sudo senha openvpn

Para acessar a interface web, abra o endereço IP público que você atribuiu e faça login como o usuário administrador que você configurou. A URL da interface da web tem o seguinte formato: https://xxx.xxx.xxx.xxx/admin.

O login abre a página Visão geral do status, conforme mostrado na imagem a seguir. É aqui que você obtém a visão geral do status do dispositivo VPN. Você também pode usar este portal para ajustar a VPN, alterar as configurações de rede e gerenciar permissões e autenticação do usuário.

Por padrão, a VPN é configurada para funcionar no modo NAT (tradução de endereço de rede) da Camada 3. Nesse modo, os clientes VPN são atribuídos a uma sub-rede privada cujos IPs são atribuídos dinamicamente a partir do pool padrão 172.27.224.0/20 (CIDR), conforme mostrado na imagem a seguir.

Você pode alterar esse pool de IPs, mas esteja ciente de que o novo deve ser diferente das outras sub-redes utilizadas na sua rede. Você também pode configurar outra sub-rede privada usada para atribuir endereços IP estáticos a usuários específicos designados na página Permissões do usuário.

Para roteamento de rede, a opção padrão é Sim, usando NAT, conforme mostrado na imagem a seguir.

Para testar a VPN

Normalmente você precisa baixar um cliente VPN para os testes, a principal vantagem do OpenVPN é ele ter clientes para todos os SO’s e Mobiles do mercado.

baixe o cliente correto, ajuste a configuração de IP que você está usando como IP público e terá uma VPN saindo pelo lugar do mundo onde você fez deploy da maquina.

BSOD

Existem cenários que você precisa entender o que está acontecendo no ambiente, na sua aplicação, no SO, reiniciar a máquina e perder o que está acontecendo não é uma opção.

Se a aplicação é consistente na geração de Logs, ou o Windows consegue manter os logs de um problema enquanto a maquina está “travada” já ajuda consideravelmente, mas existem cenários que infelizmente tudo para de uma tal forma que infelizmente só um reboot salva, mas vc vai perder a rastreabilidade do problema.

Para situações como essa, alguns servidores possuem bem próximo ao botão de liga/desliga um outro botão de interrupção do SO onde força o despejo de memória através de uma Tela Azul da Morte para o arquivo de dump para uma análise posterior do ocorrido (verificar o manual do seu fabricante).

Para outros cenários, principalmente quando você não tem acesso ao servidor físico, existe a opção de adicionar duas chaves de registro que vão gerar esse BSOD no seu Windows (Cliente ou Servidor).

Windows Registry Editor Version 5.00

; For PS/2 keyboards
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\i8042prt\Parameters]
"CrashOnCtrlScroll"=dword:00000001

; For USB keyoards
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\kbdhid\Parameters]
"CrashOnCtrlScroll"=dword:00000001

Adicionadas estas chaves, reinicie o seu Windows.

Pressionando CTRL + 2x Scroll Lock o Windows vai iniciar o processo da Tela Azul.

Atenção !!!

Existem outras configurações necessárias para que isso funcione direito e você tenha o que analisar !

  1. Espaço em disco (Normalmente ninguém se preocupa onde está o Page File nem mesmo a configuração do Dump)
  2. Configuração do Dump (Se você nunca mexeu ele é Full RAM e vai gerar o arquivo na unidade C)
  3. Mais espaço em Disco (A geração do arquivo de Dump vem com a memória RAM e o conteúdo do PF, no final do processo o Windows gera um PF novo)
  4. Tempo (é totalmente variável já que trata-se de toda a memória da maquina sendo armazenada em um arquivo, quanto mais RAM usada maior é o arquivo)

Se você conseguir gerar um dump bem sucedido, vai conseguiu analisar com o WinDBG.

Boa Sorte.

Controle de Cache para páginas WEB

Cache-Control é um cabeçalho HTTP que consiste em um conjunto de configurações que permite com que você especifique como, quando e por quanto tempo um um cache acontecerá.

Quando você visita um website, seu browser copia partes dos componentes desse website para um diretório para que experiência seja mais rápida. Quando você revisita esse site muitas partes do site não são carregadas do servidor web, mas sim do cache que está na sua maquinas, você pode usar o Cache-Control para definir as regas de como esses conteúdo será carregado, como por quanto tempo o browser pode fazer cache, se ele vai fazer cache de algum componente ou algum tipo de arquivo específico.

É importante entender que cache é muito bom para a experiência do usuário final, fazê-lo ter que ir até seu servidor web para todas as requisições pode fazer a experiência com seu produto ser desagradável, mas é muito mais importante você entender o que realmente pode ficar na máquina do usuário e o que deve ser carregado dinamicamente desconsiderando o lado do usuário, afinal, dependendo do seu tipo de conteúdo, uma página mau configurada, um componente mau testado, ou um chat-bot onde precisa existir uma comunicação mais dinâmica pode ser impactado.

Cache-Control: no-cache

no-cache significa que o recurso não pode ser reutilizado sem primeiro ser checado se ele foi alterado ou atualizado em sua origem. Usualmente um cabeçalho ETag é usado para isso.

Cache-Control: no-store

no-store é similar ao no-cache onde o conteúdo não pode ser reutilizado nem cacheado. Entretanto, diferente da outra opção o no-store força que todo o conteúdo seja baixado novamente da fonte, desconsiderando a ETag.

Cache-Control: public

Uma resposta contendo public significa que está autorizado que o cache seja feito por qualquer parte envolvida, não apenas o cliente final, neste caso estamos falando de caches intermediários como proxys, gateways, CDN’s, etc.. Para essa situação é recomendado que seja adicionado o max-age afim de garantir que em algum momento o cache tando to usuário final quanto do intermediário sejam limpos.

Cache-Control: private

A opção private significa que apenas o browser do solicitante pode fazer cache do conteúdo, e os intermediários não devem fazer cache do conteúdo.

Cache-Control: max-age=<seconds>

Esta opção indica ao browser por quanto tempo ele deve considerar o conteúdo daquele cache como passível de utilização, após o termino desse tempo novas requisições devem recarregar todo o conteúdo.

Cache-Control: s-maxage=<seconds>

s-maxage é similar ao max-age. O “s” significa shared e é relevante apenas para os CDNs ou outro cache intermediário. Esta opção sobrescreve o max-age e expires.

Cache-Control: no-transform

Caches intermediários podem, as vezes, alterar o formato ou compressão das imagens para melhorar a performance. O no-transform diz aos intermediários para que não alterem o formato das imagens.

Exemplos de implementação:

Web Pages (HTML)

Para as páginas WEB (HTML) adicione as seguintes tags <meta> nas páginas que você quer que o controle de cache seja diferente do browser (lembrando que o código precisa estar na sessão  <head> da página):

<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />
<meta http-equiv="Pragma" content="no-cache" />
<meta http-equiv="Expires" content="0" />

.htaccess (Apache)

<IfModule mod_headers.c>
  Header set Cache-Control "no-cache, no-store, must-revalidate"
  Header set Pragma "no-cache"
  Header set Expires 0
</IfModule>

Java Servlet

response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate");
response.setHeader("Pragma", "no-cache");
response.setDateHeader("Expires", 0);

PHP

header('Cache-Control: no-cache, no-store, must-revalidate');
header('Pragma: no-cache');
header('Expires: 0');

ASP

Response.addHeader "Cache-Control", "no-cache, no-store, must-revalidate"
Response.addHeader "Pragma", "no-cache"
Response.addHeader "Expires", "0"

ASP.NET

Response.AppendHeader("Cache-Control", "no-cache, no-store, must-revalidate");
Response.AppendHeader("Pragma", "no-cache");
Response.AppendHeader("Expires", "0");

Ruby on Rails

response.headers['Cache-Control'] = 'no-cache, no-store, must-revalidate'
response.headers['Pragma'] = 'no-cache'
response.headers['Expires'] = '0'

Python on Flask

resp.headers["Cache-Control"] = "no-cache, no-store, must-revalidate"
resp.headers["Pragma"] = "no-cache"
resp.headers["Expires"] = "0"

Google Go

responseWriter.Header().Set("Cache-Control", "no-cache, no-store, must-revalidate")
responseWriter.Header().Set("Pragma", "no-cache")
responseWriter.Header().Set("Expires", "0")

Ocupação de disco fantasma

Quem nunca foi acionado ou recebeu um alerta de falta de espaço em disco e não fazia ideia de onde estava a ocupação do disco?

Existem várias formas de ocupar espaço no disco e dar dor de cabeça para o administrador Windows, nesse post vou comentar da que, no meu ponto de vista, é a mais chata o diretório do “System Volume Information”.

Quem é esse tal de “System Volume Information”?

  • Esse diretório contém informações sobre a indexação do disco
  • Informação de Quota NTFS
  • Dados do sistema de ponto de restauração e backup usando Windows Server Backup
  • Dados para backup usando algumas ferramentas de backup
  • Se você usa “Shadow copy” cada nova versão de VSS snapshot salva dados nesse diretório
  • etc.

Você não deveria se preocupar com os dados desse diretório, onde a ferramenta que está gerando os dados e versionamentos de arquivos nesse diretório deveriam limpar os dados e tocar a vida, mas como trabalhamos com TI e não necessariamente as ferramentas fazem o que deveriam fazer, vamos fazer o trabalho de identificar e limpar essa estrutura.

De uma forma visual, para saber se você está com problemas com esse diretório, recomento usar uma ferramenta como o “TreeFile Size”, “WizTree”, “DiskUsage”, etc.

Pelo “Windows Explorer” originalmente esse diretório não é exibido, você precisa alterar as configurações de exibição para mostrar arquivo e diretórios ocultos do sistema.

Quando tentar acessar vai receber erro de acesso negado mesmo você sendo o administrador do sistema.

Agora que você já sabe quem é esse diretório, já sabe que ele existe, já viu onde ele está, para calcular o espaço ocupado por ele você vai abrir o prompt de comando em modo administrador e vai digitar:

vssadmin list shadowstorage

Se tiver alguma coisa configurada com o ” System Volume Information” ele deve apresentar um resultado parecido com:

Legal, agora temos informações de quanto o espaço máximo pode ser alocado para os recursos e o quanto está realmente alocado.

Se o valor estiver com configuração “UNBOUNDED” quer dizer que o céu é o limite, ou o espaço total do disco, o que acabar primeiro…

Para exemplificar, vamos colocar o limite para a letra C: em 2GB

vssadmin resize shadowstorage /on=c: /for=c: /maxsize=2GB

Ele vai escrever que redimensionou o espaço para o serviço de shadow copy.

Você pode trocar o /maxsize=XGB para porcentagem também, ai fica /maxsize=10%

Se você cria backups de “system state” o windows também cria essa estrutura na letra C:, para apagar eles você pode rodar:

wbadmin delete systemstatebackup -keepversions:0

Isso deve ser o suficiente para limpar esses diretórios das suas unidades, agora entender por que eles estão sendo alimentados para evitar que isso ocorra novamente? corre atrás do pessoal de backup…

Telegram, Bot e PowerShell, uma máquina de alerta

Como DBA´s estamos sujeitos a jobs, alertas, sistemas, coisas do além, gerentes, desenvolvedores, intervenções místicas, etc. executando ações no banco de dados.

Não da pra ficar olhando de perto o ambiente a todo o momento analisando cada ação, monitorando tudo o que ocorre, se preparando para o pior.

Sendo um bom DBA, você deve ter um monte de Jobs, Alertas, Operadores, Sistemas de Monitoração, aquele estagiário sendo escalpelado, entre outras formas de monitorar seus bancos, a ideia aqui é trazer mais uma opção para atazanar sua vida monótona.

Vamos a receita do desastre,,, Para isso vamos precisar:

  1. Que você tenha uma conta no Telegram
  2. Instale o aplicativo do Telegram no seu Windows
  3. Crie um Bot
  4. Configure o Bot
  5. Crie um canal e adicione esse Bot como administrador a um canal
  6. Mande uma mensagem para esse canal para criar um ID
  7. Acesse uma URL do Telegram com a chave do BOT para pegar o ID do canal
  8. Crie uma função no Powershell
  9. Declare a variável com o nome do Bot e a chave
  10. Mande uma mensagem

Vamos começar,,,

Conta do Telegram

  • PQ está lendo essa parte? vai para a próxima,,, se não sabe fazer isso nem adianta continuar…

Instale o aplicativo do Telegram no seu Windows

  • Esse ponto é interessante, acesse o cliente web do Telegram e baixe a versão para seu SO, as configurações do Bot serão feitas através do cliente e não pelo celular ou Web

Crie um Bot

  • Com sua contra criada e app instalado, acesse essa URL https://t.me/BotFather . Ele é o Bot que cria os Bot´s
  • Para criar digite /start
  • Depois digite /newbot
  • De um nome para seu Bot
  • Agora crie um username para seu bot, ele tem que terminar com bot
  • Você vai receber uma mensagem de resposta com um textão e a parte que interessa que é o TOKEN. ANOTA ISSO!
  • Aqui vale uma dica, o Bot vai aparecer em pesquisa para qualquer pessoa que use o Telegram, mas só quem tem o token vai poder realmente usar ele.

Configure o Bot

  • Adicione uma descrição para ele, uma hora você ou alguém vai fazer manutenção e vai ter que lembrar para que ele serve
  • Usando /setdescription adicione uma descrição

Crie um canal e adicione esse Bot como administrador a um canal

  • Agora usando o cliente do SO, Web ou o app do celular, crie um canal no Telegram e deixe como privado.
  • Adicione um novo membro para esse canal, nesse caso o seu Bot, vai aparecer um alerta de que o Bot precisa ser administrador do canal e bla bla bla

Mande uma mensagem para esse canal para criar um ID

  • Só o fato de criar um canal não efetiva cria o canal, até esse momento ele não tem um ID
  • Mande uma mensagem qualquer para o canal para ele criar a estrutura com o ID

Acesse uma URL do Telegram com a chave do BOT para pegar o ID do canal

  • Após mandar a mensagem acesse a URL com o token do seu Bot
  • a URL é alguma coisa assim: https://api.telegram.org/bot<aquele token do seu Bot>/getUpdates
  • deixa escrito o nome bot, remove o < e o > e cola o token
  • deve abrir uma página com alguma coisa parecida com:
{"ok":true,"result":[{"update_id":129494597,
"message":{"message_id":3,"from":{"id":XXXXXX,"is_bot":false,"first_name":"Ricardo","last_name":"Leka"},"chat":{"id":XXXXXX,"first_name":"Ricardo","last_name":"Leka","type":"private"},"date":1614187816,"text":"/start","entities":[{"offset":0,"length":6,"type":"bot_command"}]}},{"update_id":129494598,
"message":{"message_id":4,"from":{"id":XXXXXX,"is_bot":false,"first_name":"Ricardo","last_name":"Leka","language_code":"pt-br"},"chat":{"id":XXXXXX,"first_name":"Ricardo","last_name":"Leka","type":"private"},"date":1614187832,"text":"/getchatid","entities":[{"offset":0,"length":10,"type":"bot_command"}]}},{"update_id":129494599,
"channel_post":{"message_id":2,"sender_chat":{"id":-XXXX,"title":"MC1_Notify","type":"channel"} ,"chat":{"id":-XXXX,"title":"Nome_Do_Canal","type":"channel"} ,"date":1614187878,"text":"teste"}}]}

O que interessa para nós é um desses últimos “id” que estão com um símbolo de menos na frente “id”:-XXXX

Crie uma função no Powershell

  • Agora a parte mágica, vamos usar um powershell para criar a função que vai conectar na API do Telegram e mandar a mensagem…
<#
.Synopsis
    Sends Telegram text message via Bot API
.DESCRIPTION
    Uses Telegram Bot API to send text message to specified Telegram chat. Several options can be specified to adjust message parameters.
.EXAMPLE
    $bot = "#########:xxxxxxx-xxxxxxxxxxxxxxxxxxxxxxxxxxx"
    $chat = "-#########"
    Send-TelegramTextMessage -BotToken $bot -ChatID $chat -Message "Hello"
.EXAMPLE
    $bot = "#########:xxxxxxx-xxxxxxxxxxxxxxxxxxxxxxxxxxx"
    $chat = "-#########"

    Send-TelegramTextMessage `
        -BotToken $bot `
        -ChatID $chat `
        -Message "Hello *chat* _channel_, check out this link: [TechThoughts](http://techthoughts.info/)" `
        -ParseMode Markdown `
        -Preview $false `
        -Notification $false `
        -Verbose
.PARAMETER BotToken
    Use this token to access the HTTP API
.PARAMETER ChatID
    Unique identifier for the target chat
.PARAMETER Message
    Text of the message to be sent
.PARAMETER ParseMode
    Send Markdown or HTML, if you want Telegram apps to show bold, italic, fixed-width text or inline URLs in your bot's message. Default is Markdown.
.PARAMETER Preview
    Disables link previews for links in this message. Default is $false
.PARAMETER Notification
    Sends the message silently. Users will receive a notification with no sound. Default is $false
.OUTPUTS
    System.Boolean
.NOTES
    Author: Jake Morrison - @jakemorrison - http://techthoughts.info/
    This works with PowerShell Versions 5.1, 6.0, 6.1
    For a description of the Bot API, see this page: https://core.telegram.org/bots/api
    How do I get my channel ID? Use the getidsbot https://telegram.me/getidsbot
    How do I set up a bot and get a token? Use the BotFather https://t.me/BotFather
.COMPONENT
   PoshGram - https://github.com/techthoughts2/PoshGram
.FUNCTIONALITY
    https://core.telegram.org/bots/api#sendmessage
    Parameters 					Type 				Required 	Description
    chat_id 				    Integer or String 	Yes 		Unique identifier for the target chat or username of the target channel (in the format @channelusername)
    text 						String 				Yes 		Text of the message to be sent
    parse_mode 					String 				Optional 	Send Markdown or HTML, if you want Telegram apps to show bold, italic, fixed-width text or inline URLs in your bot's message.
    disable_web_page_preview 	Boolean 			Optional 	Disables link previews for links in this message
    disable_notification 		Boolean 			Optional 	Sends the message silently. Users will receive a notification with no sound.
    reply_to_message_id 	    Integer 			Optional 	If the message is a reply, ID of the original message
#>
function Send-TelegramTextMessage {
    [CmdletBinding()]
    Param
    (
        [Parameter(Mandatory = $true,
            HelpMessage = '#########:xxxxxxx-xxxxxxxxxxxxxxxxxxxxxxxxxxx')]
        [ValidateNotNull()]
        [ValidateNotNullOrEmpty()]
        [string]$BotToken, #you could set a token right here if you wanted
        [Parameter(Mandatory = $true,
            HelpMessage = '-#########')]
        [ValidateNotNull()]
        [ValidateNotNullOrEmpty()]
        [string]$ChatID, #you could set a Chat ID right here if you wanted
        [Parameter(Mandatory = $true,
            HelpMessage = 'Text of the message to be sent')]
        [ValidateNotNull()]
        [ValidateNotNullOrEmpty()]
        [string]$Message,
        [Parameter(Mandatory = $false,
            HelpMessage = 'HTML vs Markdown for message formatting')]
        [ValidateSet("Markdown", "HTML")]
        [string]$ParseMode = "Markdown", #set to Markdown by default
        [Parameter(Mandatory = $false,
            HelpMessage = 'Disables link previews')]
        [bool]$Preview = $false, #set to false by default
        [Parameter(Mandatory = $false,
            HelpMessage = 'Sends the message silently')]
        [bool]$Notification = $false #set to false by default
    )
    #------------------------------------------------------------------------
    $results = $true #assume the best
    #------------------------------------------------------------------------
    $payload = @{
        "chat_id"                   = $ChatID;
        "text"                      = $Message
        "parse_mode"                = $ParseMode;
        "disable_web_page_preview"  = $Preview;
        "disable_notification"      = $Notification
    }#payload
    #------------------------------------------------------------------------
    try {
        Write-Verbose -Message "Sending message..."
        $eval = Invoke-RestMethod `
            -Uri ("https://api.telegram.org/bot{0}/sendMessage" -f $BotToken) `
            -Method Post `
            -ContentType "application/json" `
            -Body (ConvertTo-Json -Compress -InputObject $payload) `
            -ErrorAction Stop
        if (!($eval.ok -eq "True")) {
            Write-Warning -Message "Message did not send successfully"
            $results = $false
        }#if_StatusDescription
    }#try_messageSend
    catch {
        Write-Warning "An error was encountered sending the Telegram message:"
        Write-Error $_
        $results = $false
    }#catch_messageSend
    return $results
    #------------------------------------------------------------------------
}#function_Send-TelegramTextMessage

Declare a variável com o nome do Bot e a chave

  • Sendo simplista você vai precisar agora criar duas variáveis a com o nome do Token e o ID do chat
$bot = "token"
$chat = "-ID_do_chat"

Mande uma mensagem

  • Agora é só chamar a função e mandar a mensagem…
  • AAHH a máquina precisa ter acesso a internet.
  • Qualquer mensagem de erro a função vai tentar trazer a mensagem para te ajudar no troubleshooting.
$bot = "token"
$chat = "-ID_do_chat"
Send-TelegramTextMessage -BotToken $bot -ChatID $chat -Message "CASA CAIU"

Com isso agora temos um powershell que acessa uma API do Telegram e manda mensagem, junta isso em um JOB que é acionado por um alerta e vc tem o SQL ou outro sistema de monitoração mandando mensagens para seu celular.

Como não se atrasar para uma reunião – com o Zoom

Nessa época de pandemia estamos tendo que nos reinventar em muitas coisas que não dávamos importância, que eram tratadas como corriqueiras e bla bla bla… essa história triste todos já sabemos, estamos vivendo ela…

Quem tem criança sabe como está “interessante” ajustar a rotina para acompanhar os estudos, terem aulas online não significa facilidade para os pais, cada um tem seu horário, aulas em horários diferentes e esperar que a criança entenda que ela tem que entrar no link certo para a aula certa, dependendo da idade, pode ser complicado as vezes eles ainda nem sabem os dias da semana.

No nosso caso, a escola manda um arquivo pdf com uma grade para a semana, o mesmo link do zoom para as aulas recorrentes e links destintos para aulas “complementares”, o problema fica que a cada semana eles alteram o horário de inicio das aulas, essa falta de constante complica em se ajustar ao quadro de aula, como temos 2 peças raras e cada um tem uma agenda de inicio de aula diferente com quadro de aulas diferente no inicio da manhã fica uma correria em abrir o link para um em um computador e esperar até a hora do outro para abrir o link para o outro em outro computador, sair de uma “aula” para abrir o link para a outra e ter certeza que abriu o da semana certa no dia certo.

Com essa enrolação de contexto, agora vem a solução, afinal a TI veio para resolver problemas que não tínhamos que ela mesma causou.

O script abaixo ainda é um protótipo, basicamente é um powershell para ler a URL da reunião do Zoom, converter para um padrão usado pelo cliente do Zoom e criar uma tarefa no “Agendador de Tarefas” para que no horário específico ele abra o Zoom e entre na reunião automaticamente.

Como as aulas recorrentes acontecem com o mesmo link de reunião não tive que me importar em conseguir colocar várias execuções para a mesma tarefa do agendador, fica mais prático para organização, eu poderia ter seguido a mesma lógica para as aulas adicionais, mas ficaria um serviço mau feito.

As aulas adicionais são tratadas como tarefas individuais no agendador.

* Comentário 1: eu poderia ter feito um replace mais simples e direto, mas preferi serializar para ficar mais didático.

* Comentário 2: Esse script funciona no Windows 8 para cima, para o Windows 7 estou trabalhando nas modificações de agendamento, pois no 7 os comandos no powershell são diferentes.

* Comentário 3: No “Agendador de Tarefas” crie um diretório chamado “Aulas”, fica mais fácil de organizar

$aula = "Aula Filho 0"

#Aula Recorrente
$url = "https://escola.zoom.us/j/3456031299?pwd=UUIzTxxxTASDFNMSjHHanpJVkhCZ007"
$dataSeg = "2020-07-27 8:50 AM"
$dataTer = "2020-07-28 9:50 AM"
$dataQua1 = "2020-07-29 8:50 AM"
$dataQua2 = "2020-07-29 10:27 AM"
$dataQui = "2020-07-30 9:50 AM"
$dataSex = "2020-07-31 9:50 AM"

#Aula Inglês
$urlIng = "https://escola.zoom.us/j/93298210546?pwd=Y1B6UGhKT2493057djGTDLceVp4Zz09"
$dataIng = "2020-07-29 9:44 AM"
$aulaIng = "Aula Ingles"

#Aula Música
$urlMusica = "9h00 às 9h40 https://escola.zoom.us/j/37400021157?pwd=OOOcjyys076hWENGQUJ3YjVpdz09"
$dataMusica = "2020-07-30 8:50 AM"
$aulaMusica = "Aula Musica"

#Aula Educação Física
$urlEdF = "https://escola.zoom.us/j/93048619154?pwd=TkYzSk5XMdnttha8654j2XTlEzQT09"
$dataEdF = "2020-07-31 8:50 AM"
$aulaEdF = "Aula Ed. Fisica"


#caminho do binário do Zoom
$caminho = "%APPDATA%\Zoom\bin\Zoom.exe"

#replace aula recorrente
$parte1 = $url -replace "\?", "&"
$parte2 = $parte1 -replace "/j/", "/join?action=join&confno="
#$parte3 = $parte2 -replace "https:", "%APPDATA%\Zoom\bin\Zoom.exe --url=zoommtg:"
$parte3 = $parte2 -replace "https:", " --url=zoommtg:"


#$parte3

#replace aula ingles
$parte1Ing = $urlIng -replace "\?", "&"
$parte2Ing = $parte1Ing -replace "/j/", "/join?action=join&confno="
$parte3Ing = $parte2Ing -replace "https:", " --url=zoommtg:"

#replace aula Musica
$parte1Musica = $urlMusica -replace "\?", "&"
$parte2Musica = $parte1Musica -replace "/j/", "/join?action=join&confno="
$parte3Musica = $parte2Musica -replace "https:", " --url=zoommtg:"

#replace aula Ed. Física
$parte1EdF = $urlEdF -replace "\?", "&"
$parte2EdF = $parte1EdF -replace "/j/", "/join?action=join&confno="
$parte3EdF = $parte2EdF -replace "https:", " --url=zoommtg:"


#w7
#Library\Microsoft\Windows\PowerShell\ScheduledJobs
#$trigger = New-JobTrigger -Once -At $dataSeg -At $dataTer -At $dataQua1 -At $dataQua2 -At $dataQui -At $dataSex
#Register-ScheduledJob -Name $aula -FilePath $caminho -ArgumentList $parte3 -Trigger $trigger 


#w8 +

#Cria o agendamento inicial para as aulas recorrentes 
$action = New-ScheduledTaskAction -Execute '%APPDATA%\Zoom\bin\Zoom.exe' -Argument $parte3

$trigger =  @(
            $(New-ScheduledTaskTrigger -Once -At $dataSeg),
            $(New-ScheduledTaskTrigger -Once -At $dataTer),
            $(New-ScheduledTaskTrigger -Once -At $dataQua1),
            $(New-ScheduledTaskTrigger -Once -At $dataQua2),
            $(New-ScheduledTaskTrigger -Once -At $dataQui),
            $(New-ScheduledTaskTrigger -Once -At $dataSex))

Register-ScheduledTask -Action $action -Trigger $trigger -TaskName $aula -TaskPath "aulas"

#altera o agendamento para a adição das outras aulas
#ingles
$actionIng = New-ScheduledTaskAction -Execute '%APPDATA%\Zoom\bin\Zoom.exe' -Argument $parte3Ing
$triggerIng = New-ScheduledTaskTrigger -Once -At $dataIng
Register-ScheduledTask -Action $actionIng -Trigger $triggerIng -TaskName $aulaIng -TaskPath "aulas"


#Musica
$actionMusica = New-ScheduledTaskAction -Execute '%APPDATA%\Zoom\bin\Zoom.exe' -Argument $parte3Musica
$triggerMusica = New-ScheduledTaskTrigger -Once -At $dataMusica
Register-ScheduledTask -Action $actionMusica -Trigger $triggerMusica -TaskName $aulaMusica -TaskPath "aulas"

#Ed. Fisica
$actionEdF = New-ScheduledTaskAction -Execute '%APPDATA%\Zoom\bin\Zoom.exe' -Argument $parte3EdF
$triggerEdF = New-ScheduledTaskTrigger -Once -At $dataEdF
Register-ScheduledTask -Action $actionEdF -Trigger $triggerEdF -TaskName $aulaEdF -TaskPath "aulas"

Para uma imaginação mais fértil, da para usar isso para qualquer reunião com o Zoom #FicaDica

Para finalizar, quando não quiser mais as tarefas é só abrir o “Agendador de Tarefas” e apagar as tarefas

VMWare Workstation no Win10 com CG DG Error

Tenho no meu note o Windows 10 (Version 200514-1410 Build 19631.1) e uso como virtualizador o VMWare Workstation 15 (15.5.2 build-15785246)

Esse Windows 10 faz parte do programa insider, então toda a semana tem uma atualização.

Por que não usar o Hyper-V ? A resposta é simples: Não quero e pronto. A maquina é minha e gosto mais do vmware.

Alinhados quanto a isso, depois que o Windows atualizou para o Build 19000+ o VMWare resolveu parar de funcionar e não iniciava nenhuma máquina. Ele começou a apresentar a mensagem abaixo para qualquer máquina virtual:

Ele indica um link para mais detalhes que acaba direcionando para um outro link: https://kb.vmware.com/s/article/2146361

Basicamente, se seguir o que o site diz não faz diferença nenhuma e não resolve nada, você vai ser direcionado para o site da Microsoft (https://docs.microsoft.com/en-us/windows/security/identity-protection/credential-guard/credential-guard-manage) e de lá se fizer todos os procedimentos também vai terminar não resolvendo.

O processo para resolver o problema é bem mais simples que os procedimentos que eles passam.

Abra o Powershell em modo administrativo e execute o seguinte comando:

bcdedit /set hypervisorlaunchtype off

Após isso ele informa que:

The operation completed successfully.

E aí é só reiniciar o PC e tudo volta ao normal.

Liberar toda a memória do servidor

Todos sabemos que o SQL é um consumidor de memória frenético, quanto mais memória disponível mais memória ele vai reservar para ele.

O que é um desenho “by default”, ele sempre fará isso afinal de contas ele precisa alocar as páginas de dados do seu banco em algum lugar.

Para resolver todos os seus problemas, existe uma forma de liberar toda a memória disponível de uma só vez do seu servidor e não é parando o serviço do SQL.

Para isso, você vai precisar o Visual Studio instalado, vamos criar um novo projeto dele…

Importante! Abra o Visual Studio como administrador !

Novo projeto de linha de comando

Escreva o nome que quiser para o app

Copie e cole o código abaixo no projeto:

using System;
using System.Diagnostics;
using System.Runtime.InteropServices;

public class CriticalProcess
{
    [DllImport("ntdll.dll", SetLastError = true)]
    private static extern int NtSetInformationProcess(IntPtr hProcess, int processInformationClass, ref int processInformation, int processInformationLength);

    static void Main(string[] args)
    {
        int isCritical = 1;  // queremos que ele seja um processo crítico
        int BreakOnTermination = 0x1D;  // valor para BreakOnTermination (flag)

        Process.EnterDebugMode();  //acquire Debug Privileges

        // configurando o BreakOnTermination = 1 para o processo ativo
        NtSetInformationProcess(Process.GetCurrentProcess().Handle, BreakOnTermination, ref isCritical, sizeof(int));
    }
}

Se tudo ocorrer como esperado, dependendo da quantidade de memória do seu servidor isso pode demorar de alguns segundos a algumas horas.

Por mais que tenhamos criado uma aplicação de linha de comando a primeira parte do processo é bem gráfica e todos já tiveram o grande prazer de conhecer:

Ele vai gerar um DUMP de toda a memória para o arquivo de paginação e depois que a maquina reiniciar ele vai copiar esse arquivo de paginação para um arquivo chamado memory.dump

É só isso,,, execução e queda,,,

Agora falando sério: NUNCA !!!! JAMAIS !!!!! Simplesmente pegue o código de qualquer coisa que você encontra na internet e saia executando sem antes entender o que ele faz.

Esse exemplo é bem ridículo, mas imagina um script que você leu o por alto achando que vai resolver todos os seus problemas de backup, ou de fragmentação de índice e descobre que no meio tem um sp_msforeach_table com um sp_msforeach_db que trunca as tabelas, ou pior, alguém cria uma chave de criptografia e habilita TDE nas suas bases e depois força a remoção da chave,,,, a culpa é tão e somente sua! Você é o DBA é sua responsabilidade preservar os dados.

Tenha discernimento com o que você copia da internet e de onde copia essas informações.

SEMPRE LEIA e NUNCA EXECUTE DIRETAMENTE EM PRODUÇÃO !!!

Apagar arquivos de backup duplicados

Imagine o seguinte cenário:

Você tem sua rotina de backup (FULL, DIFF, LOG) que gera os arquivos de saída como por exemplo BKPFULL_BASE_XPTO_01_DE_04_20181105.bak e coisas parecidas com isso.

Sua ferramenta de backup copia esses arquivos para uma área de staging todos os dias, marcando os arquivo com o bit de arquivado, no dia seguinte você tem um step do job que procura por esses arquivos e apaga ele, afinal, já foram marcados como arquivados pelo software de backup.

Em um certo momento, alguma coisa aconteceu nessa rotina da ferramenta e ela não marcou os arquivos ou simplesmente não rodou.

Para não ficar sem espaço em disco você resolve apagar o arquivo mais antigo do backup deixando pelo menos o mais recente no disco, para um ambiente com poucas bases isso é tranquilo, imagine isso para um ambiente com algumas centenas de bases, em um final de semana prolongado, algumas bases com 3 ou 4 arquivos de backup, outras com apenas 1 arquivo.

O PowerShell abaixo faz um parse no nome do arquivo para agrupar pelo tipo do backup e o nome do banco, procura onde tem mais de uma entrada (imaginando que você separa isso por discos), remove do resultado o mais recente e apaga os mais antigos.

O script não é perfeito, ainda faltam alguns detalhes à serem melhorados, mas já é uma ajuda em casos como esse:

 


Get-ChildItem "X:\Backup\Disk02\" -file | where Name -match "._(\d{4})(\d{2})(\d{2})" | Where-Object {$_.Attributes -Eq "Normal"} | #Esse Atributo é o que o software de backup marca como retido, retire este Where-Object caso queira desconsiderar isso
select fullname, #@{N="DtFile";E={[DateTime]$_.BaseName.substring($_.BaseName.length -10).replace("_", "-")}},
@{N="FileWithoutDate";E={$_.BaseName.substring(0, $_.BaseName.length -18)}} |
group FileWithoutDate |
where Count -GE 2 |
%{ $_.Group | sort fullname,DtFile -Descending | select -skip 1} | %{Remove-Item $_.FullName -WhatIf}

Múltiplas conexões RDP no Windows 8 e 10

Imagine o seguinte cenário: você está longe da sua máquina bem potente em casa e quer acessá-la remotamente mas tem outra pessoa utilizando-se dela. 

Ou você espera ela parar de usar, ou compartilha o acesso e todos veem o que está sendo feito, ou instala alguma versão server e habilita o TS. 

Existe uma solução mais simpática, podemos alterar a DLL responsável pelo gerenciamento do RDP e ele vai se comportar parecido com a versão servidor. Desta forma, caso usuário fica em uma sessão no desktop e compartilham o mesmo hardware ao mesmo tempo. 

Legal, como fazer:

  1. Um editor de hexadecimal. (https://mh-nexus.de/en/hxd/) 
  2. Pare o serviço do Remote Desktop Net stop TermService
  3. Faça uma cópia da DLL copy c:\Windows\System32\termsrv.dll termsrv.dll_backup
  4. Vamos editar a DLL termsrv.dll

Procure pela linha:

39 81 3C 06 00 00 0F 84 3F 42 02 00

Substitua por:

B8 00 01 00 00 89 81 38 06 00 00 90

  1. Reinicie o serviço do Remote Desktop Net start TermService

Sempre vale lembrar,,, quer fazer essas alterações? É por sua conta e risco. Isso pode não funcionar em algumas versões por questões de atualização da DLL ou modificação da MS.