火曜日, 4月 04, 2023

SQL Server の tempdb のファイルを削除

 サーバマシンのサイズ変更等で、CPUのコア数が減り、tempdb のファイルも減らす必要が生じた場合の作業例。(SQL Server の再起動なしにはできなかった。)

 Management Studio でつぎのSQL文を実行する。

USE [master];
GO
ALTER DATABASE tempdb MODIFY FILE
(NAME = temp5, SIZE = 1KB, FILEGROWTH = 0 );
GO
ALTER DATABASE tempdb MODIFY FILE
(NAME = temp6, SIZE = 1KB, FILEGROWTH = 0 );
GO
ALTER DATABASE tempdb MODIFY FILE
(NAME = temp7, SIZE = 1KB, FILEGROWTH = 0 );
GO
ALTER DATABASE tempdb MODIFY FILE
(NAME = temp8, SIZE = 1KB, FILEGROWTH = 0 );
GO

 この後、SQL Server のサービスを再起動する。
 さらに、Management Studio でつぎのSQL文を実行する。

USE [tempdb];
GO
DBCC SHRINKFILE (N'temp5' , EMPTYFILE);
GO
ALTER DATABASE [tempdb] REMOVE FILE [temp5];
GO
DBCC SHRINKFILE (N'temp6' , EMPTYFILE);
GO
ALTER DATABASE [tempdb] REMOVE FILE [temp6];
GO
DBCC SHRINKFILE (N'temp7' , EMPTYFILE);
GO
ALTER DATABASE [tempdb] REMOVE FILE [temp7];
GO
DBCC SHRINKFILE (N'temp8' , EMPTYFILE);
GO
ALTER DATABASE [tempdb] REMOVE FILE [temp8];
GO

以上。

月曜日, 11月 07, 2022

GithubからダウンロードしたWindows Terminalのインストーラーがエラーで失敗した場合(Windows 10 Pro 21H1)

https://github.com/microsoft/terminal/releases/

から最新安定板のインストーラー(Microsoft.WindowsTerminal_Win10_1.15.2874.0_8wekyb3d8bbwe.msixbundle)をダウンロードし、起動してインストールを開始すると

Windows ターミナルのインストールに失敗しました。

アプリ インストーラーで、パッケージの依存関係をインストールできませんでした。開発元に  パッケージを要求してください。 

と表示され、インストールに失敗した。

https://xn--learn-r83d.microsoft.com/en-us/troubleshoot/developer/visualstudio/cpp/libraries/c-runtime-packages-desktop-bridge#how-to-install-and-update-desktop-framework-packages

から Microsoft.VCLibs.x64.14.00.Desktop.appx をダウンロードしてインストール後、再度実行すると、正しくインストールされた。

木曜日, 3月 24, 2022

Selenium から Headless Chrome on Ubuntu 20.04 のサンプル (Perl の Selenium::Remote::Driver)

IDとパスワードでログインし、ログイン後の画面のスクリーンショットを撮るPerlのサンプルソース。 
Selenium::Remote::Driver は、ユーザhogehogeがcpanmでインストールした前提。

----- ここから -----
#!/usr/bin/env perl

use strict;
use warnings;
use lib '/home/hogehoge/perl5/lib/perl5';
use Selenium::Chrome;

my $logon_url = 'https://www.hogehoge.com/';
my $user_id = 'foobar';
my $password  = 'password';
my $png_path = 'sample.png';

my $driver = Selenium::Chrome->new(
  extra_capabilities => {
    'goog:chromeOptions' => {
      args => ['headless', 'disable-gpu', 'window-size=1920,1080', 'no-sandbox' ]
    }
  }
);

$driver->get($logon_url);

$driver->find_element_by_name('user_id')->send_keys($user_id);
sleep 1;

$driver->find_element_by_name('password')->send_keys($password);
sleep 1;

$driver->find_element("//input[\@type='submit']")->click();
sleep 5;

$driver->capture_screenshot("$png_path");

$driver->quit();

exit;
----- ここまで -----

以上。

Ubuntu 20.04 でPerl用モジュール Selenium::Remote::Driver をインストール

まず、Google Chrome と  Selenium 用chromedriver、IPA日本語フォントをインストール。
つぎに、cpanm を使えるようにするインストール。
そして、Selenium::Remote::Driver のdebパッケージはないので、cpanmでインストール。
最後に .bashrc にパスを追記。

$ sudo sh -c 'echo "deb http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google-chrome.list'
$ sudo apt -y install wget gnupg
$ sudo wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | sudo apt-key add -
$ sudo apt update
$ sudo apt -y install google-chrome-stable chromium-chromedriver fonts-ipafont
$ fc-cache -fv
$
$ sudo apt -y install gcc make cpanminus
$ cpanm Selenium::Remote::Driver
$
$ vi .bashrc
 (以下を追記)
export PERL_CPANM_OPT="--local-lib=~/perl5"
export PATH=$HOME/perl5/bin:$PATH;
export PERL5LIB=$HOME/perl5/lib/perl5:$PERL5LIB;
$
$ source .bashrc

以上。

木曜日, 9月 12, 2019

テキストファイルの文字コード、改行コードを変換

カレントディレクトリ以下のファイルの文字コードをシフトJISからUTF-8に、改行コードをCR+LFからLFに変換する。
また、ファイル内の文字列Windows-31JまたはShift_JISをUTF-8に置換する。

$ find . -type f -print0 | xargs -0 perl -MEncode -i.bak -pe 'Encode::from_to($_,"cp932","utf-8"); s/\r\n/\n/g; s/(Windows-31J|Shift_JIS)/UTF-8/g;'
$ find . -name "*.bak" -print0 | xargs -0 rm -f

水曜日, 1月 16, 2019

SQL Serverで実行されたクエリを取得する

例えば、実行時刻が2019/01/16 16:10:00以降でクエリが「hogehoge」を含むものを取得する場合

SELECT st.text, last_execution_time
FROM sys.dm_exec_query_stats qs
CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) st
WHERE last_execution_time >= '2019/01/16 16:10:00' AND st.text like '%hogehoge%'
ORDER BY last_execution_time

Azure Database for MySQL にバーチャルネットワークからだけ接続可能にする

 Microsoft AzureのMySQLのPaaSであるAzure Database for MySQLには、特定のIPアドレスからのみ接続できるようにする設定のほか、特定のバーチャルネットワークからのみ接続できるようにする設定も可能。

(1) バーチャルネットワークの「サービスエンドポイント」を「Microsoft.Sql」で追加する。

(2) Azure Database for MySQLの「接続のセキュリティ」で「既存の仮想ネットワークを追加」する。
なお、この設定ができるのは、「価格レベル」がBasic以外でなければならない。

 これらの設定の後、当該バーチャルネットワーク内の仮想マシンからMySQLに接続できるようになる。
 接続の際のログイン名とサーバ名は、Azure Database for MySQLの「プロパティ」で確認できる。

MySQLに接続する際は、

$ mysql -u ログイン名 -p -h サーバ名 --ssl

のようにSSLで接続するオプションを指定する。

火曜日, 11月 27, 2018

Azure Face APIサンプル 2(カメラ利用)

Azureの管理ポータルでの設定は省略。
HTMLファイルのサンプル。
カメラつき端末のHTML5対応ブラウザの利用が前提。
httpdのドキュメントルート下の /cognitive/ に配置される前提。
なお、ここで利用するPHPファイルは「Azure Face APIサンプル」を参照。

face_api2.html
----- ここから -----
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<meta name="robots" content="noindex,nofollow" />
<meta http-equiv="Pragma" content="no-cache" />
<meta http-equiv="Cache-Control" content="no-cache" />
<meta http-equiv="Expires" content="0" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Face API (with camera)</title>

<link rel="stylesheet" href="//stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous" />
<style>
<!--
@media all {
  .page-title {
    color: #555555;
    font-size: x-large;
    font-weight: bold;
    text-shadow: 1px 1px 1px #999999;
  }
  #canvas {
    display: none;
  }
  #result {
    font-size: large;
    font-weight: bold;
    text-shadow: 1px 1px 1px #333333;
  }
}

@media screen and (max-width: 480px) {
  #player {
    width: 90%;
    width: 90vw;
  }
  #canvas {
    display: none;
    width: 90%;
    width: 90vw;
  }
}
-->
</style>
</head>
<body>
<div class="container">

<div class="row">
<div class="col-sm-12">
<nav class="navbar navbar-expand-sm navbar-dark bg-dark">
<a class="navbar-brand" href="/cognitive/">Cognitive Services Examples</a>
</nav>
</div>
</div>

<div class="row">
<div class="col-sm-12">
<h3 class="page-title">Face API (with camera)</h3>
</div>
</div>
<br />

<div class="row">
<div class="col-sm-12">
<strong> カメラのある端末でかつHTML5対応ブラウザでこのページを表示し、カメラに顔を向け「カメラで撮影」ボタンをクリックしてください。</strong>
<div class="card">
<div class="card-body">
<button type="button" id="submit-btn" class="btn btn-primary">カメラで撮影</button>
 <button type="button" id="reset-btn" class="btn btn-info">リセット</button>
</div>
</div>
</div>
</div>
<br />

<div class="row">
<div class="col-sm-12">
<div class="mx-auto" style="width: 100%;">
<video id="player" controls playsinline muted autoplay></video>
</div>
</div>
</div>

<div class="row">
<div class="col-sm-12">
<canvas id="canvas"></canvas>
</div>
</div>
<br />

<div class="row">
<div class="col-sm-5">
<div id="result"></div>
</div>
</div>
<br />

</div>

<!-- template -->
<script type="text/template" id="result-table-template">
<table class="table table-bordered">
<tr>
<td colspan="2">性別</td><td><div class="float-sm-right"><%= gender %></div></td>
</tr>
<tr>
<td colspan="2">年齢</td><td><div class="float-sm-right"><%= age %></div></td>
</tr>
<tr>
<td colspan="2">眼鏡</td><td><div class="float-sm-right"><%= glasses %></div></td>
</tr>
<tr>
<td rowspan="8">感情</td><td>Anger (怒り)</td><td><div class="float-sm-right"><%= anger %></div></td>
</tr>
<tr>
<td>Contempt (軽蔑)</td><td><div class="float-sm-right"><%= contempt %></div></td>
</tr>
<tr>
<td>Disgust (嫌悪)</td><td><div class="float-sm-right"><%= disgust %></div></td>
</tr>
<tr>
<td>Fear (恐怖)</td><td><div class="float-sm-right"><%= fear %></div></td>
</tr>
<tr>
<td>Happiness (幸福)</td><td><div class="float-sm-right"><%= happiness %></div></td>
</tr>
<tr>
<td>Neutral (ニュートラル)</td><td><div class="float-sm-right"><%= neutral %></div></td>
</tr>
<tr>
<td>Sadness (悲しみ)</td><td><div class="float-sm-right"><%= sadness %></div></td>
</tr>
<tr>
<td>Surprise (驚き)</td><td><div class="float-sm-right"><%= surprise %></div></td>
</tr>
<tr>
<td rowspan="2">化粧</td><td>目</td><td><div class="float-sm-right"><%= eyeMakeup %></div></td>
</tr>
<tr>
<td>口</td><td><div class="float-sm-right"><%= lipMakeup %></div></td>
</tr>
</table>
</script>

<!-- javascript -->
<script src="//cdnjs.cloudflare.com/ajax/libs/underscore.js/1.9.1/underscore-min.js" integrity="sha256-G7A4JrJjJlFqP0yamznwPjAApIKPkadeHfyIwiaa9e0=" crossorigin="anonymous"></script>
<script src="//code.jquery.com/jquery-3.3.1.min.js" integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=" crossorigin="anonymous"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery.blockUI/2.70/jquery.blockUI.min.js" integrity="sha256-9wRM03dUw6ABCs+AU69WbK33oktrlXamEXMvxUaF+KU=" crossorigin="anonymous"></script>
<script>
(function() {

"use strict";

const root = this;
const _    = root._;
const $    = root.jQuery;

const apiUrl = '/cognitive/face_api.php';
const resultTableTemplate
  = _.template($('#result-table-template').html());

const mathRound = function(val) {
  return (val * 100).toFixed(2);
};

const toBlob = function(base64, type) {
  const bin = atob(base64.replace(/^.*,/, ''));
  const buffer = new Uint8Array(bin.length);
  for (let i = 0; i < bin.length; i++) {
    buffer[i] = bin.charCodeAt(i);
  }

  const blob = new Blob([buffer.buffer], {
    type: type
  });
  return blob;
};

$(function() {
  const player = document.getElementById('player');
  const canvas = document.getElementById('canvas');
  const context = canvas.getContext('2d');
  const fd = new FormData();
  const maxPixels = 4096;

  navigator.mediaDevices.getUserMedia({
    audio: false,
    video: {
      facingMode: 'user'
    }
  }).then(function(stream) {
    player.srcObject = stream;
  });

  $('#reset-btn').on('click', function() {
    $('#result').html("");
    $('#canvas').hide();
    $('#player').show();
  });

  $('#submit-btn').on('click', function() {
    $('#result').html("");
    $('#player').hide();
    $('#canvas').show();

    const date = new Date();
    const fileName = date.getTime() + '.jpg';
    let scale = 1;
    if (player.videoWidth > player.videoHeight && player.videoWidth > maxPixels) {
      scale = maxPixels / player.videoWidth;
    }
    else if (player.videoWidth < player.videoHeight && player.videoHeight > maxPixels) {
      scale = maxPixels / player.videoHeight;
    }
    canvas.width = player.videoWidth * scale;
    canvas.height = player.videoHeight * scale;
    context.drawImage(player, 0, 0, player.videoWidth, player.videoHeight, 0, 0, canvas.width, canvas.height);
    fd.append("img-file", toBlob(canvas.toDataURL('image/jpeg'), 'image/jpeg'), fileName);
    $.blockUI({
      message : '<img src="/common/img/gif-load.gif" />',
      css : {
        color : '',
        border : '',
        backgroundColor : ''
      },
      overlayCSS : {
        backgroundColor: '#FFFFFF'
      }
    });

    $.ajax({
      url : apiUrl + '?api_type=detect&returnFaceAttributes=age,gender,smile,facialHair,glasses,headPose,emotion,hair,makeup,accessories',
      type : "POST",
      data: fd,
      processData: false,
      contentType : false,
      dataType : "json"
    }).done(function(data, status, xhr) {
      for (let i in data) {
        $('#result').append(
          '<span id="result' + (i + 1) + '">'
          + resultTableTemplate({
              gender : data[i].faceAttributes.gender === 'male' ? '男性' : '女性',
              age : data[i].faceAttributes.age,
              glasses : data[i].faceAttributes.glasses === 'NoGlasses' ? 'なし' : 'あり',
              anger : mathRound(data[i].faceAttributes.emotion.anger),
              contempt : mathRound(data[i].faceAttributes.emotion.contempt),
              disgust : mathRound(data[i].faceAttributes.emotion.disgust),
              fear : mathRound(data[i].faceAttributes.emotion.fear),
              happiness : mathRound(data[i].faceAttributes.emotion.happiness),
              neutral : mathRound(data[i].faceAttributes.emotion.neutral),
              sadness : mathRound(data[i].faceAttributes.emotion.sadness),
              surprise : mathRound(data[i].faceAttributes.emotion.surprise),
              eyeMakeup : data[i].faceAttributes.makeup.eyeMakeup === true ? 'あり' : 'なし',
              lipMakeup : data[i].faceAttributes.makeup.lipMakeup === true ? 'あり' : 'なし',
            })
          + '</span><br />'
        );

        context.beginPath();
        if (i % 7 === 0) {
          context.strokeStyle = 'rgb(255, 0, 0)';
          $('#result' + (i + 1)).css('color', '#FF0000');
        }
        else if (i % 7 === 1) {
          context.strokeStyle = 'rgb(0, 255, 0)';
          $('#result' + (i + 1)).css('color', '#00FF00');
        }
        else if (i % 7 === 2) {
          context.strokeStyle = 'rgb(0, 0, 255)';
          $('#result' + (i + 1)).css('color', '#0000FF');
        }
        else if (i % 7 === 3) {
          context.strokeStyle = 'rgb(0, 255, 255)';
          $('#result' + (i + 1)).css('color', '#00FFFF');
        }
        else if (i % 7 === 4) {
          context.strokeStyle = 'rgb(255, 255, 0)';
          $('#result' + (i + 1)).css('color', '#FFFF00');
        }
        else if (i % 7 === 5) {
          context.strokeStyle = 'rgb(255, 0, 255)';
          $('#result' + (i + 1)).css('color', '#FF00FF');
        }
        else if (i % 7 === 6) {
          context.strokeStyle = 'rgb(0, 0, 0)';
          $('#result' + (i + 1)).css('color', '#000000');
        }
        context.strokeRect(data[i].faceRectangle.left, data[i].faceRectangle.top, data[i].faceRectangle.width, data[i].faceRectangle.height);
      }
    }).fail(function(xhr, status, error) {
      console.log(JSON.stringify(xhr));
      console.log(status);
      console.log(error);
    }).always(function() {
      $(document).ajaxStop($.unblockUI);
    });
  });
});

}).call(this);
</script>

</body>
</html>
----- ここまで -----