Symfoware

Symfowareについての考察blog

PythonでUPnPによるポートマップ(なぜなに Torrent)

なぜなに Torrent ( P2P プログラム入門 )

こちらを参考に、PythonでTorrentクライアントを作ってみます。
最終目標は、Debianのインストーラーをダウンロードしてみること。

最小の CD を使って、ネットワークインストールする


前回までで、Torrentファイルの内容を読み取ることができました。
PythonでBencodingのデコード(なぜなに Torrent)

今回は、UPnPによるポートマップを試してみます。
UPnPによるポートマップ



UPnPによるポートマップ




UDP Multicast を利用して、使用中のルーターに、ポートマッピングを依頼するためのアドレスを教えてもらう。
TCP を使って、教えてもらったアドレスからポートマッピングの依頼をだす。



ルーターにこんな機能があったとは。知りませんでした。

Pythonでの実装はこちらを参考にしています。
DLNAってなんじゃらほい? - SSDPを喋ってみる -
UPnPを使ってルータの外向けIPアドレスを取得する




依頼先を調べる



UDPマルチキャストでUPnPに対応しているルーターの情報を調べます。

送信するデータ


M-SEARCH * HTTP/1.1
MX: 3
HOST: 239.255.255.250:1900
MAN: "ssdp:discover"
ST: urn:schemas-upnp-org:service:WANIPConnection:1





Pythonでの実装はこうなりました。


  1. # -*- coding:utf-8 -*-
  2. import socket
  3. host = '239.255.255.250'
  4. port = 1900
  5. messages = [
  6.     'M-SEARCH * HTTP/1.1',
  7.     'MX: 3',
  8.     'HOST: 239.255.255.250:1900',
  9.     'MAN: "ssdp:discover"',
  10.     'ST: urn:schemas-upnp-org:service:WANIPConnection:1',
  11. ]
  12. message = '\r\n'.join(messages)
  13. message += '\r\n\r\n' # 末尾に改行コードを2つ付与
  14. sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
  15. sock.sendto(message, (host, port))
  16. res = sock.recv(4096)
  17. print(res)
  18. sock.close()




実行してみるとこんな応答があります。


$ python sample.py
HTTP/1.1 200 OK
CACHE-CONTROL: max-age=1800
DATE: Thu, 11 May 2017 13:08:30 GMT
EXT:
LOCATION: http://192.168.1.1:49152/gatedesc.xml
SERVER: Linux/3.2.26, UPnP/1.0, Intel SDK for UPnP devices/1.3.1
ST: urn:schemas-upnp-org:service:WANIPConnection:1
USN: uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx::urn:schemas-upnp-org:service:WANIPConnection:1





重要なのは「LOCATION」の情報です。
このURLをブラウザで開くと、xmlで情報が表示されます。


「serviceType」が「urn:schemas-upnp-org:service:WANIPConnection:1」となっているタグの、
「controlURL」が重要です。

このURLに対して、SOAP通信で要求を行っていくことになります。

751_01.png



UDPマルチキャストでUPnPに対応しているルーターの情報を取得。
応答の「LOCATION」からxmlを取得・解析し、controlURLを取得するまでのプログラムはこうなりました。


  1. # -*- coding:utf-8 -*-
  2. import socket
  3. import urllib
  4. import urlparse
  5. import xml.etree.ElementTree as ET
  6. # --- ルーターの情報を取得
  7. host = '239.255.255.250'
  8. port = 1900
  9. messages = [
  10.     'M-SEARCH * HTTP/1.1',
  11.     'MX: 3',
  12.     'HOST: 239.255.255.250:1900',
  13.     'MAN: "ssdp:discover"',
  14.     'ST: urn:schemas-upnp-org:service:WANIPConnection:1',
  15. ]
  16. message = '\r\n'.join(messages)
  17. message += '\r\n\r\n' # 末尾に改行コードを2つ付与
  18. sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
  19. sock.sendto(message, (host, port))
  20. res = sock.recv(4096)
  21. sock.close()
  22. for line in res.split('\n'):
  23.     info = line.strip()
  24.     if not info.startswith('LOCATION:'):
  25.         continue
  26.     
  27.     locaction = info[len('LOCATION:'):].strip()
  28.     break
  29.     
  30. print 'locaction:', locaction
  31. # --- XMLの解析
  32. f = urllib.urlopen(locaction)
  33. xml_string = f.read()
  34. f.close()
  35. xml = ET.fromstring(xml_string)
  36. ns = {
  37.     'ns' : 'urn:schemas-upnp-org:device-1-0'
  38. }
  39. # controlURLを取得する
  40. for child in xml.findall(".//ns:service", ns):
  41.     if child.find('ns:serviceType', ns).text == 'urn:schemas-upnp-org:service:WANIPConnection:1':
  42.         controlURL = child.find('ns:controlURL', ns).text
  43.         break
  44.     
  45. print controlURL
  46. print urlparse.urljoin(locaction, controlURL)





実行結果


$ python sample.py
locaction: http://192.168.1.1:49152/gatedesc.xml
/upnp/control/WANIPConn1
http://192.168.1.1:49152/upnp/control/WANIPConn1




試行錯誤しながらなので不格好ですが、希望通りSOAPアクションを送信する
http://192.168.1.1:49152/upnp/control/WANIPConn1
というURLが取得できました。





外部の端末から見えているアドレスを聞く



SOAP通信、何かライブラリを使用しても良かったのですが、urllibだけでも行けそうだったので、
素のpythonだけで実装してみます。

Can I use urllib to submit a SOAP request?
4.2. Python XML HTTP Post to send a SOAP message to a JWSDP or to a .NET web service.


  1. # -*- coding:utf-8 -*-
  2. import socket
  3. import urllib2
  4. import urlparse
  5. import xml.etree.ElementTree as ET
  6. # --- ルーターの情報を取得
  7. host = '239.255.255.250'
  8. port = 1900
  9. messages = [
  10.     'M-SEARCH * HTTP/1.1',
  11.     'MX: 3',
  12.     'HOST: 239.255.255.250:1900',
  13.     'MAN: "ssdp:discover"',
  14.     'ST: urn:schemas-upnp-org:service:WANIPConnection:1',
  15. ]
  16. message = '\r\n'.join(messages)
  17. message += '\r\n\r\n' # 末尾に改行コードを2つ付与
  18. sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
  19. sock.sendto(message, (host, port))
  20. res = sock.recv(4096)
  21. sock.close()
  22. for line in res.split('\n'):
  23.     info = line.strip()
  24.     if not info.startswith('LOCATION:'):
  25.         continue
  26.     
  27.     locaction = info[len('LOCATION:'):].strip()
  28.     break
  29.     
  30. print 'locaction:', locaction
  31. # --- XMLの解析
  32. f = urllib2.urlopen(locaction)
  33. xml_string = f.read()
  34. f.close()
  35. xml = ET.fromstring(xml_string)
  36. ns = {
  37.     'ns' : 'urn:schemas-upnp-org:device-1-0'
  38. }
  39. # controlURLを取得する
  40. for child in xml.findall(".//ns:service", ns):
  41.     if child.find('ns:serviceType', ns).text == 'urn:schemas-upnp-org:service:WANIPConnection:1':
  42.         controlURL = child.find('ns:controlURL', ns).text
  43.         break
  44.     
  45. print controlURL
  46. get_ip_soap = """<?xml version="1.0"?>
  47. <s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"
  48.      s:encodingStyle="http://schemas.xmlsoap.org/encoding/">
  49. <s:Body>
  50.     <m:GetExternalIPAddress xmlns:m="urn:schemas-upnp-org:service:WANIPConnection:1">
  51.     </m:GetExternalIPAddress>
  52. </s:Body>
  53. </s:Envelope>"""
  54. soap_url = urlparse.urljoin(locaction, controlURL)
  55. req = urllib2.Request(soap_url, data=get_ip_soap)
  56. req.add_header("Content-type", "text/xml; charset=\"UTF-8\"")
  57. req.add_header("SOAPAction", '"urn:schemas-upnp-org:service:WANIPConnection:1#GetExternalIPAddress"')
  58. response = urllib2.urlopen(req)
  59. ret = response.read()
  60. print 'Response:' + '-' * 10
  61. print ret




実行結果


  1. $ python sample.py
  2. locaction: http://192.168.1.1:49152/gatedesc.xml
  3. /upnp/control/WANIPConn1
  4. Response:----------
  5. <s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"><s:Body>
  6. <u:GetExternalIPAddressResponse xmlns:u="urn:schemas-upnp-org:service:WANIPConnection:1">
  7. <NewExternalIPAddress>93.184.216.34/NewExternalIPAddress>
  8. </u:GetExternalIPAddressResponse>
  9. </s:Body> </s:Envelope>




ちゃんと外向きのIPアドレスが取得できました。





【参考URL】

DLNAってなんじゃらほい? - SSDPを喋ってみる -
UPnPを使ってルータの外向けIPアドレスを取得する
Can I use urllib to submit a SOAP request?
4.2. Python XML HTTP Post to send a SOAP message to a JWSDP or to a .NET web service.
UPnPのNAT越えについて調べてみた

関連記事

テーマ:プログラミング - ジャンル:コンピュータ

  1. 2017/05/11(木) 23:37:29|
  2. Python
  3. | トラックバック:0
  4. | コメント:0
  5. | 編集

PythonでBencodingのデコード(なぜなに Torrent)

なぜなに Torrent ( P2P プログラム入門 )

こちらを参考に、PythonでTorrentクライアントを作ってみます。
最終目標は、Debianのインストーラーをダウンロードしてみること。

最小の CD を使って、ネットワークインストールする



Torrentファイルを読み込む



https://nazenani-torrent.firefirestyle.net/torrentfile/Torrentfile.html

Torrentファイルは、bencodeという形式で記載されているそうです。
データ型は4つ。


・文字列(String)

[文字の長さ(バイト数)]:[文字]

という形式で表現。

「Hello」は、「5:Hello」
「こんにちは」は、「10:こんにちは」
となるようです。



・整数(Number)

i[数字]e

とい形式で表現。

「123」は「i123e」
「1024」は「i1024e」
となるようです。



・リスト(List)

順序を持った複数のデータを保持します。


l[要素1][要素2]...[要素n]e

という形式で表現。


Pythonでの配列
['Hello', 'こんにちは']、これは「l5:Hello10:こんにちはe」
[123, 1024]、これは「li123ei1024ee」
となるようです。



・辞書(Dict)

キーワードと値を関連付けてデータを保持します。

d[キー要素1][値要素1][キー要素2][値要素2]...[キー要素n][値要素n]e

という形式で表現。

キーが「Hello」、値が「こんにちは」の場合「d5:Hello10:こんにちはe」
となるようです。





torrentファイルの内容




実際のtorrentファイルの中身を確認してみます。

最小の CD を使って、ネットワークインストールする
こちらから「debian-8.7.1-amd64-netinst.iso.torrent」をダウンロード。

バイナリエディタで内容を確認してみます。

750_01.png

「d」から始まるので辞書型で、次は数値なので、コロン以降に文字列が続いて...
確かに読み取れますね。




パーサー



適当にパーサーを書いて、ファイルの中身を解析してみます。


  1. # -*- coding:utf-8 -*-
  2. class MyTorrent(object):
  3.     def parse_file(self, torrent_file):
  4.         
  5.         with open(torrent_file, 'rb') as f:
  6.             result = self.parse(f.read())
  7.             
  8.         return result
  9.     
  10.     
  11.     def parse(self, bencode_bytes):
  12.         
  13.         result = []
  14.         while(bencode_bytes):
  15.         
  16.             # 数値
  17.             if bencode_bytes[0] == 'i':
  18.                 v,bencode_bytes = self.parse_number(bencode_bytes)
  19.                 
  20.             # リスト
  21.             elif bencode_bytes[0] == 'l':
  22.                 v,bencode_bytes = self.parse_list(bencode_bytes)
  23.                 
  24.             # 辞書
  25.             elif bencode_bytes[0] == 'd':
  26.                 v,bencode_bytes = self.parse_dict(bencode_bytes)
  27.             
  28.             # 解析途中で打ち切り
  29.             elif bencode_bytes[0] == 'e':
  30.                 return (result, bencode_bytes[1:])
  31.             
  32.             # 文字列
  33.             else:
  34.                 v,bencode_bytes = self.parse_string(bencode_bytes)
  35.             
  36.             result.append(v)
  37.             
  38.         return result
  39.     
  40.     
  41.     def parse_number(self, bencode_bytes):
  42.         """ 数値部分を解析し、解析結果と未解析部分を返す """
  43.         index = bencode_bytes.find('e')
  44.         value = int(bencode_bytes[1:index])
  45.         return (value, bencode_bytes[index + 1:])
  46.         
  47.     
  48.     def parse_string(self, bencode_bytes):
  49.         """ 文字列部分を解析し、解析結果と未解析部分を返す """
  50.         index = bencode_bytes.find(':')
  51.         last_index = index + int(bencode_bytes[:index]) + 1
  52.         value = bencode_bytes[index + 1:last_index]
  53.         return (value, bencode_bytes[last_index:])
  54.         
  55.     def parse_list(self, bencode_bytes):
  56.         """ リスト部分を解析し、解析結果と未解析部分を返す """
  57.         return self.parse(bencode_bytes[1:])
  58.         
  59.     def parse_dict(self, bencode_bytes):
  60.         """ 辞書部分を解析し、解析結果と未解析部分を返す """
  61.         list_value, bencode_bytes = self.parse(bencode_bytes[1:])
  62.         value = {}
  63.         for i in range(0, len(list_value), 2):
  64.             value[list_value[i]] = list_value[i + 1]
  65.         
  66.         return value, bencode_bytes
  67. if __name__ == '__main__':
  68.     t = MyTorrent()
  69.     result = t.parse_file('debian-8.7.1-amd64-netinst.iso.torrent')
  70.     info = result[0]
  71.     
  72.     print('announce', info['announce'])
  73.     print('creation date', info['creation date'])
  74.     print('comment', info['comment'])
  75.     print('httpseeds', info['httpseeds'])
  76.     print('info.length', info['info']['length'])
  77.     print('info.piece length', info['info']['piece length'])
  78.     print('info.name', info['info']['name'])
  79.     print('info.pieces', len(info['info']['pieces']))





実行結果


$ python sample.py
('announce', 'http://bttracker.debian.org:6969/announce')
('creation date', 1484567799)
('comment', '"Debian CD from cdimage.debian.org"')
('httpseeds', ['http://cdimage.debian.org/cdimage/release/8.7.1/iso-cd/debian-8.7.1-amd64-netinst.iso', 'http://cdimage.debian.org/cdimage/archive/8.7.1/iso-cd/debian-8.7.1-amd64-netinst.iso'])
('info.length', 260046848)
('info.piece length', 262144)
('info.name', 'debian-8.7.1-amd64-netinst.iso')
('info.pieces', 19840)





・announce:Tracker サーバーのアドレス

http://bttracker.debian.org:6969/announce
ここに問い合わせれば、データを配信してくれる端末を紹介してくれるようです。


・creation date:ファイルの作成日


・comment:コメント



・info.length:ダウンロード後のサイズ

260046848 byteなので、260.0 MBぐらいになります。


・info.piece length:データを配信する際に分割するサイズ

262144 byteなので、256KBごとにファイルが分割されているようです。

ファイルの総容量 260046848 byte / 分割サイズ 262144 byte = 992

992個のファイルに分割されていると読み取れるのかと思います。


・info.name:ファイル名

debian-8.7.1-amd64-netinst.iso


・info.pieces:分割されたデータごとのHash値

20バイト単位のバイナリデータとのこと。

19840 byte / 20 byte = 992

上記で計算した分割ファイル数と一致しますね。




次は、UPnPによるポートマップを試してみようと思います。




関連記事

テーマ:プログラミング - ジャンル:コンピュータ

  1. 2017/05/05(金) 18:28:42|
  2. Python
  3. | トラックバック:0
  4. | コメント:0
  5. | 編集

UbuntuにインストールしたSQL Serverでデータベース、テーブルを作成(sqlcmd)

Ubuntu Server 16.04にSQL Serverをインストールしました。
Ubuntu Server 16.04 固定IPへの変更とSSH接続の有効化

sqlcmdを使用して、データベースとテーブルの作成を行ってみます。


sqlcmd



そういえば、sqlcmdでデータベースの作成を試したことがありました。
SQL Server 2008 R2 Express コマンドでデータベースとテーブルを作成する(sqlcmd)


sampleデータベース、postalテーブルを作成してみます。


・create.sql


USE master;
GO

CREATE DATABASE sample;
GO

USE sample;
GO

CREATE TABLE postal (
    code char(7) not null,
    address nchar(100) not null
);
GO




create.sqlというファイル名で保存しました。
sqlcmdでファイルに記載している内容を実行。


$ sqlcmd -U sa -P P@ssw0rd -i create.sql
Changed database context to 'master'.
Changed database context to 'sample'.




実行できたようです。


データの登録や検索を試してみます。
sqlcmdでデータベースに接続


$ sqlcmd -U sa -P P@ssw0rd




sampleデータベースに切り替え。


1> use sample;
2> go
Changed database context to 'sample'.




データ登録。


1> insert into postal (code,address) values ('1234567', 'テスト住所');
2> go

(1 rows affected)




登録したデータを検索。


1> select * from postal;
2> go
code    address                                                                                            
------- ----------------------------------------------------------------------------------------------------
1234567 テスト住所                                                                                            

(1 rows affected)




ちゃんと動いてくれています。
exitでsqlcmdを終了します。


1> exit
$




Management Studio上からも確認できました。

749_01.png


関連記事

テーマ:サーバ - ジャンル:コンピュータ

  1. 2017/04/26(水) 00:21:43|
  2. SQL Server
  3. | トラックバック:0
  4. | コメント:0
  5. | 編集

SQL Server 2017 照合順序のデフォルト値確認と変更

Ubuntu Server 16.04にSQL Serverをインストールしました。
Ubuntu Server 16.04 固定IPへの変更とSSH接続の有効化


そういえば、インストール時に照合順序の指定がなかったなと思ったので、
確認と変更を行ってみます。




現在の照合順序



現在の照合順序を確認するには、


  1. SELECT CONVERT (varchar, SERVERPROPERTY('collation'))



を実行すればよいようです。
照合順序情報の表示


sqlcmdを使用し、Ubuntu上で実行してみます。


$ sqlcmd -U sa -P P@ssw0rd -Q "SELECT CONVERT (varchar, SERVERPROPERTY('collation'))"
                            
------------------------------
SQL_Latin1_General_CP1_CI_AS

(1 rows affected)




現在の照合順序は「SQL_Latin1_General_CP1_CI_AS」ですね。





照合順序の変更



こちらを参考に、照合順序を「Japanese_CI_AS」へ変更してみます。
Configure SQL Server on Linux with the mssql-conf tool

「Change the SQL Server collation」の項目を参考に、コマンドを実行。


$ sudo /opt/mssql/bin/mssql-conf set-collation
Enter the collation: Japanese_CI_AS
This is an evaluation version. There are [173] days left in the evaluation period.
sqlservr: Another instance of the application is already running.



エラーで終了しました。


どうも、データベースを停止していないと変更できない模様。
一旦、mssql-serverをstopした後、コマンドを実行してみます。


$ sudo service mssql-server stop
$ sudo /opt/mssql/bin/mssql-conf set-collation
Enter the collation: Japanese_CI_AS

This is an evaluation version. There are [173] days left in the evaluation period.
2017-04-25 23:50:22.47 Server     Microsoft SQL Server vNext (CTP2.0) - 14.0.500.272 (X64)

(略)

Trace ID = '1'. This is an informational message only; no user action is required.
成功しました。SQL Server を起動するには 'sudo systemctl start mssql-server' を実行してください




データベースを起動。
再度照合順序を確認してみます。


$ sudo service mssql-server start
$ sqlcmd -U sa -P P@ssw0rd -Q "SELECT CONVERT (varchar, SERVERPROPERTY('collation'))"
                            
------------------------------
Japanese_CI_AS                

(1 rows affected)




変更できました。

Management Studioからも変更が確認できます。

748_01.png


関連記事

テーマ:サーバ - ジャンル:コンピュータ

  1. 2017/04/25(火) 23:58:25|
  2. SQL Server
  3. | トラックバック:0
  4. | コメント:0
  5. | 編集

SQL Server 2017 vNext(14.0)をUbuntu Server 16.04にインストール

SQL ServerがLinuxにインストールできるようになりました。
Ubuntu Server 16.04にインストールしてみようと思います。

SQL Server on Linux Documentation



インストール



こちらを参考にしました。
Install SQL Server on Ubuntu

※注意:搭載しているメモリは4GBないと、インストール時にエラーとなります。


apt-keyを更新。


$ curl https://packages.microsoft.com/keys/microsoft.asc | sudo apt-key add -




実行すると、sudoの入力待ちになりますので、ログインユーザーのパスワードを入力します。


$ curl https://packages.microsoft.com/keys/microsoft.asc | sudo apt-key add -
[sudo] symfo のパスワード: % Total    % Received % Xferd Average Speed Time    Time     Time Current
                                 Dload Upload Total Spent    Left Speed
100 983 100 983    0     0 1734     0 --:--:-- --:--:-- --:--:-- 1733
[ここで固まったように見えるがパスワードまち。パスワードを入力してエンター]
OK





aptのソースリストを追加。


$ curl https://packages.microsoft.com/config/ubuntu/16.04/mssql-server.list | sudo tee /etc/apt/sources.list.d/mssql-server.list




実行の様子


$ curl https://packages.microsoft.com/config/ubuntu/16.04/mssql-server.list | sudo tee /etc/apt/sources.list.d/mssql-server.list
% Total    % Received % Xferd Average Speed Time    Time     Time Current
                                 Dload Upload Total Spent    Left Speed
100    87 100    87    0     0     29     0 0:00:03 0:00:02 0:00:01    29
deb [arch=amd64] https://packages.microsoft.com/ubuntu/16.04/mssql-server xenial main




aptの内容を更新して、インストールを実行します。

その前に、apt-transport-httpsをインストールしておきます。
インストールしていないと、こんなエラーが発生します。


E: メソッドドライバ /usr/lib/apt/methods/https が見つかりません。
N: パッケージ apt-transport-https はインストールされていますか?




update,installを実行します。


$ sudo apt-get install apt-transport-https
$ sudo apt-get update
$ sudo apt-get install -y mssql-server




最初、仮想環境に2GBのメモリを割り当ててインストールを試していたのですが、
こんなエラーで終了しました。


ERROR: This machine must have at least 3.25 gigabytes of memory to install Microsoft(R) SQL Server(R).
mssql-server は終了コード 1 で前設定に失敗しました




メモリの割当を4GBに変更し、再度インストールを実行。


$ sudo apt-get install -y mssql-server

...

mssql-server (14.0.500.272-2) を設定しています ...

+--------------------------------------------------------------+
'sudo /opt/mssql/bin/mssql-conf setup' を実行し、
Microsoft SQL Server のセットアップを完了してください
+--------------------------------------------------------------+





今度は正常終了してくれました。







初期セットアップ



インストールが完了したら、指定通り初期セットアップのコマンドを実行します。


$ sudo /opt/mssql/bin/mssql-conf setup




ライセンス認証やパスワードの入力などを求められます。


$ sudo /opt/mssql/bin/mssql-conf setup

この製品のライセンス条項は、次の URL からダウンロードし
http://go.microsoft.com/fwlink/?LinkId=746388
ファイル /usr/share/doc/mssql-server/LICENSE.TXT で参照できます。

ライセンス条項に同意しますか? [Yes/No]:Yes
Microsoft SQL Server を設定しています
新しい SQL Server システム管理者パスワードを入力してください: [任意のパスワード入力]
新しい SQL Server システム管理者パスワードを確認入力してください: [上記と同じパスワード入力]
Microsoft SQL Server を開始しています...
起動時の Microsoft SQL Server の実行を有効にしています...
Created symlink from /etc/systemd/system/multi-user.target.wants/mssql-server.service to
/lib/systemd/system/mssql-server.service.
セットアップが正常に完了しました。




ここで入力したパスワードがSQL Serverのsa(管理者権限ユーザー)のパスワードになります。
systemctlを実行すると、サービスが開始されているか確認できます。


$ systemctl status mssql-server
● mssql-server.service - Microsoft SQL Server Database Engine
Loaded: loaded (/lib/systemd/system/mssql-server.service; enabled; vendor pre
Active: active (running) since 火 2017-04-25 22:58:37 JST; 1min 26s ago
     Docs: https://docs.microsoft.com/en-us/sql/linux
Main PID: 1366 (sqlservr)
CGroup: /system.slice/mssql-server.service
         ├─1366 /opt/mssql/bin/sqlservr
         └─1384 /opt/mssql/bin/sqlservr

4月 25 22:58:41 mssql sqlservr[1366]: [82B blob data]
4月 25 22:58:41 mssql sqlservr[1366]: [84B blob data]
4月 25 22:58:41 mssql sqlservr[1366]: [122B blob data]
4月 25 22:58:41 mssql sqlservr[1366]: [145B blob data]
4月 25 22:58:41 mssql sqlservr[1366]: [66B blob data]
4月 25 22:58:41 mssql sqlservr[1366]: [75B blob data]
4月 25 22:58:41 mssql sqlservr[1366]: [96B blob data]
4月 25 22:58:41 mssql sqlservr[1366]: [100B blob data]
4月 25 22:58:41 mssql sqlservr[1366]: [71B blob data]
4月 25 22:58:41 mssql sqlservr[1366]: [124B blob data]








sqlcmdのインストール



続いて、sqlcmd等のツールのインストールを行いました。
Install sqlcmd and bcp the SQL Server command-line tools on Linux


apt-keiの追加
(SQL Serverのインストールを行っている場合は不要)


$ curl https://packages.microsoft.com/keys/microsoft.asc | sudo apt-key add -




aptのソースリストを追加


$ curl https://packages.microsoft.com/config/ubuntu/16.04/prod.list | sudo tee /etc/apt/sources.list.d/msprod.list




update,installを実行します。


$ sudo apt-get update
$ sudo apt-get install mssql-tools unixodbc-dev




インストール中、ライセンス認証の画面が表示されます。
「はい」を選択してエンターキーを押下します。

747_01.png

747_02.png



ツールは「/opt/mssql-tools/bin」にインストールされます。


$ ls /opt/mssql-tools/bin
bcp sqlcmd




パスを通しておくと便利です。


$ echo 'export PATH="$PATH:/opt/mssql-tools/bin"' >> ~/.bash_profile
$ echo 'export PATH="$PATH:/opt/mssql-tools/bin"' >> ~/.bashrc
$ source ~/.bashrc




sqlcmdのヘルプを表示してみます。


$ sqlcmd -?
Microsoft (R) SQL Server Command Line Tool
Version 13.1.0006.0 Linux
Copyright (c) 2012 Microsoft. All rights reserved.

usage: sqlcmd            [-U login id]         [-P password]
[-S server or Dsn if -D is provided]
[-H hostname]         [-E trusted connection]
[-N Encrypt Connection][-C Trust Server Certificate]
[-d use database name] [-l login timeout]     [-t query timeout]
[-h headers]         [-s colseparator]     [-w screen width]
[-a packetsize]        [-e echo input]        [-I Enable Quoted Identifiers]
[-c cmdend]
[-q "cmdline query"] [-Q "cmdline query" and exit]
[-m errorlevel]        [-V severitylevel]     [-W remove trailing spaces]
[-u unicode output]    [-r[0|1] msgs to stderr]
[-i inputfile]         [-o outputfile]
[-k[1|2] remove[replace] control characters]
[-y variable length type display width]
[-Y fixed length type display width]
[-p[1] print statistics[colon format]]
[-R use client regional setting]
[-K application intent]
[-M multisubnet failover]
[-b On error batch abort]
[-D Dsn flag, indicate -S is Dsn]
[-X[1] disable commands, startup script, environment variables [and exit]]
[-x disable variable substitution]
[-? show syntax summary]



ちゃんとインストールできたようです。





別サーバーからの接続



WindowsにインストールしたSQL Server Management Studio (SSMS) から接続してみます。

認証:SQL Server認証
ログイン:sa
パスワード:インストール時に入力したパスワード

747_03.png


普通に接続できました。

747_04.png


データの保存パスを見てみると、「/var/opt/mssql/data」になっています。
ちゃんとLinuxのSQL Serverに接続できたようです。

747_05.png



関連記事

テーマ:サーバ - ジャンル:コンピュータ

  1. 2017/04/25(火) 23:28:14|
  2. SQL Server
  3. | トラックバック:0
  4. | コメント:0
  5. | 編集
次のページ