성태의 닷넷 이야기
홈 주인
모아 놓은 자료
프로그래밍
질문/답변
사용자 관리
사용자
메뉴
아티클
외부 아티클
유용한 코드
온라인 기능
MathJax 입력기
최근 덧글
[정성태] Java - How to use the Foreign Funct...
[정성태] 제가 큰 실수를 했군요. ^^; Delegate를 통한 Bein...
[정성태] Working with Rust Libraries from C#...
[정성태] Detecting blocking calls using asyn...
[정성태] 아쉽게도, 커뮤니티는 아니고 개인 블로그입니다. ^^
[정성태] 질문이 잘 이해가 안 됩니다. 우선, 해당 소스코드에서 ILis...
[양승조
] var대신 dinamic으로 선언해서 해결은 했습니다. 맞는 해...
[양승조
] 또 막혔습니다. ㅠㅠ var list = props[i].Ge...
[양승조
] 아. 감사합니다. 어제는 안됐던것 같은데....정신을 차려야겠네...
[정성태] "props[i].GetValue(props[i])" 코드에서 ...
글쓰기
제목
이름
암호
전자우편
HTML
홈페이지
유형
제니퍼 .NET
닷넷
COM 개체 관련
스크립트
VC++
VS.NET IDE
Windows
Team Foundation Server
디버깅 기술
오류 유형
개발 환경 구성
웹
기타
Linux
Java
DDK
Math
Phone
Graphics
사물인터넷
부모글 보이기/감추기
내용
<div style='display: inline'> <h1 style='font-family: Malgun Gothic, Consolas; font-size: 20pt; color: #006699; text-align: center; font-weight: bold'>.NET Core/5+ 응용 프로그램의 Ubuntu (Debian) 패키지 준비</h1> <p> .NET Core/5+의 다중 플랫폼 지원이 무르익었으니, 이제 리눅스에서 흔히 사용하던 "apt install ..."로도 설치할 수 있는 패키지를 만들어 보고 싶어질 것입니다. ^^<br /> <br /> 마침 이에 대해 소개한 글이 있는데요,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > Packaging a .NET Core Service for Ubuntu ; <a target='tab' href='https://medium.com/bluekiri/packaging-a-net-core-service-for-ubuntu-4f8e9202d1e5'>https://medium.com/bluekiri/packaging-a-net-core-service-for-ubuntu-4f8e9202d1e5</a> </pre> <br /> 위의 글을 좀 정리해서 실습해 보겠습니다. ^^<br /> <br /> <hr style='width: 50%' /><br /> <br /> 처음엔 nuget 등의 방식과 다르지 않겠거니... 했는데... 은근히 다릅니다. ^^; 그렇다고는 해도 일종의 manifest 정보가 있어야 한다는 점에서는 다르지 않은데요, 그럼 당연히 1차로 그 정보부터 구성해 봐야겠지요. ^^<br /> <br /> 이를 위해 "<a target='tab' href='https://medium.com/bluekiri/packaging-a-net-core-service-for-ubuntu-4f8e9202d1e5'>Packaging a .NET Core Service for Ubuntu</a>" 글에서는 dh_make라는 도구를 이용하는데요, 그것을 위해 프로젝트를 빌드한 바이너리의 tar.gz까지 구성하는 등의 절차를 거칩니다. 하지만 실제 해보고 나니 그 절차가 딱히 필수 단계는 아니었습니다. 왜냐하면 만들어지는 파일들이 거의 정형화되어 있기 때문입니다.<br /> <br /> 즉, 수작업으로 직접 구성해도 무방한데요, 예를 들어 c:\temp 디렉터리에 구성한다고 했을 때 temp 하위에 임의의 디렉터리를 만들고, 다시 그 하위에 "debian" 디렉터리, 다시 그 하위에 "source" 디렉터리를 만듭니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > /* buildroot를 제외한 모든 경로 및 파일은 대/소문자 구분 */ .\buildroot (임의의 이름) \debian (고정 이름) \source (고정 이름) </pre> <br /> 그다음 각각의 디렉터리에 텍스트 파일들을 생성합니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > .\buildroot\debian changelog control copyright rules .\buildroot\debian\source format </pre> <br /> <hr style='width: 50%' /><br /> <br /> 그럼 이제 텍스트 파일의 내용을 하나씩 채워볼까요? ^^ 우선, .\buildroot\debian\source\format 파일은 다음의 내용을 채우면 됩니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > 3.0 (native) </pre> <br /> 그다음 .\buildroot\debian\source\rules 파일의 내용을 이렇게 채웁니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > #!/usr/bin/make -f %: dh $@ </pre> <br /> shebang을 보면 짐작할 수 있듯이 Makefile인데요, 이에 대한 내용은 나중에 채울 테니 여기서는 이렇게만 설정하고 지나갑니다.<br /> <br /> 그다음 .\buildroot\debian\source\copyright 파일은 여러분들이 만드는 패키지의 라이선스를 명시하면 됩니다. 아래는 dh_make를 이용해 만든 MIT 라이선스 템플릿 파일에 Upstream-Name과 Copyright만 바꾼 것입니다. 느낌대로 여러분의 상황에 맞게 적절한 값을 채우면 됩니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ <span style='color: blue; font-weight: bold'>Upstream-Name: testapp</span> Upstream-Contact: <preferred name and address to reach the upstream project> Source: <url://example.com> Files: * Copyright: <years> <put author's name and email here> <years> <likewise for another author> License: MIT Files: debian/* <span style='color: blue; font-weight: bold'>Copyright: 2021 Test User <testuser@test.com></span> License: MIT License: MIT Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: . The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. . THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # Please also look if there are files or directories which have a # different copyright/license attached and list them here. # Please avoid picking licenses with terms that are more restrictive than the # packaged work, as it may make Debian's contributions unacceptable upstream. # # If you need, there are some extra license texts available in two places: # /usr/share/debhelper/dh_make/licenses/ # /usr/share/common-licenses/ </pre> <br /> 그다음 .\buildroot\debian\changelog 파일도 역시 dh_make가 만든 템플릿 파일을 적절하게 수정했습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > <span style='color: blue; font-weight: bold'>testapp (1.0-0ubuntu1) bionic</span>; urgency=medium * Initial Release. -- <span style='color: blue; font-weight: bold'>Test User <testuser@test.com></span> Sat, 17 Jul 2021 13:20:21 +0900 </pre> <br /> 위의 "testapp (1.0-0ubuntu1) bionic"에서 괄호 안의 버전은 다음과 같은 의미를 갖습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > 1.0: upstream version 0: Debian version ubuntu1: Ubuntu version 1 bionic: 우분투의 release 코드명 </pre> <br /> 마지막으로, .\buildroot\debian\control 파일은 기본값에서 약간 바꿀 것이 많지만 어려운 내용은 아닙니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > <span style='color: blue; font-weight: bold'>Source: testapp</span> <span style='color: blue; font-weight: bold'>Section: utils</span> Priority: optional <span style='color: blue; font-weight: bold'>Maintainer: Test User <testuser@test.com></span> Build-Depends: debhelper-compat (= 12) Standards-Version: 4.4.1 <span style='color: blue; font-weight: bold'>Homepage: https://www.sysnet.pe.kr</span> <span style='color: blue; font-weight: bold'>Package: testapp</span> Architecture: any Depends: ${shlibs:Depends}, ${misc:Depends} <span style='color: blue; font-weight: bold'>Description: sample package app This package is just a sample package app written in bash shell script</span> </pre> <br /> Source, Maintainer, Homepage, Package 필드는 감각적으로 기입할 수 있을 것입니다. Section의 경우에는 자신이 만드는 패키지의 목적에 따라 다음의 문서를 보고,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > 2.4. Sections ; <a target='tab' href='https://www.debian.org/doc/debian-policy/ch-archive.html#sections'>https://www.debian.org/doc/debian-policy/ch-archive.html#sections</a> </pre> <br /> 적절한 값을 찾아 기입하면 됩니다. 그리고, Description의 경우에는 60자 이내로 쓰되, 자세한 패키지 설명은 위의 파일에서처럼 개행을 한 후 한 칸 들여 쓰기를 해 텍스트를 입력하면 됩니다. 즉, 위의 파일에서는 다음과 같은 의미를 갖습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > short desc: sample package app long desc: This package is just a sample package app written in bash shell script </pre> <br /> 기타 좀 더 자세한 controls 파일의 사양은 다음의 문서를 참조합니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > Control files and their fields ; <a target='tab' href='https://www.debian.org/doc/debian-policy/ch-controlfields.html'>https://www.debian.org/doc/debian-policy/ch-controlfields.html</a> </pre> <br /> <hr style='width: 50%' /><br /> <br /> manifest의 구성은 저걸로 끝입니다. 자, 저걸 기반으로 우리가 만들 .NET Core 응용 프로그램을 담아야 하는데요, 이게 (nuget의 경우처럼) 바이너리를 직접 담는 것이 아니라 소스 코드를 담은 후 "rules" Makefile을 이용해 빌드하는 식입니다.<br /> <br /> 여기서는 간단하게 "dotnet new console" 명령어로 생성된 Hello World 콘솔 응용 프로그램을 실습할 텐데요, 그렇게 해서 생성된 프로젝트를 c:\temp\buildroot에 복사합니다. 따라서 최종 디렉터리 및 파일은 다음과 같은 식으로 마련돼야 합니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > C:\temp> <span style='color: blue; font-weight: bold'>tree /f</span> Folder PATH listing Volume serial number is C02C-196F C:. └───buildroot │ <span style='color: blue; font-weight: bold'>Program.cs</span> │ <span style='color: blue; font-weight: bold'>testapp.csproj</span> │ └───debian │ changelog │ control │ copyright │ rules │ └───source format </pre> <br /> 이제 저 프로젝트를 빌드해 배포 바이너리를 만드는 것을 아까 미뤘던 rules Makefile에 지정해야 합니다. 하지만, 그 전에 "배포 바이너리"를 만들기 위한 csproj 설정을 다음과 같이 추가합니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > <Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <OutputType>Exe</OutputType> <TargetFramework>net5.0</TargetFramework> <RootNamespace>testapp</RootNamespace> <span style='color: blue; font-weight: bold'><!-- 우분투 대상 바이너리 생성 --> <RuntimeIdentifier>ubuntu.18.04-x64</RuntimeIdentifier> <!-- PDB 정보도 내장해 주고 --> <DebugType>embedded</DebugType> <!-- 편의상 출력 경로에서 runtime id는 제거 --> <AppendRuntimeIdentifierToOutputPath>false</AppendRuntimeIdentifierToOutputPath> <AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath> <!-- .NET 설치 의존성을 없애고 --> <SelfContained>true</SelfContained> <!-- 최소 용량의 단일 파일로 --> <PublishTrimmed>true</PublishTrimmed> <PublishSingleFile>true</PublishSingleFile></span> </PropertyGroup> <span style='color: blue; font-weight: bold'><!-- 크기를 줄이기 위해 --> <ItemGroup> <RuntimeHostConfigurationOption Include="System.Globalization.Invariant" Value="true" /> </ItemGroup></span> </Project> </pre> <br /> 여러분의 경우 적절하게 옵션을 추가/삭제하시면 됩니다. 마지막으로 위의 프로젝트를 빌드해 바이너리 파일을 담도록 rules 파일을 다음과 같이 구성합니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > #!/usr/bin/make -f %: dh $@ <span style='color: blue; font-weight: bold'>override_dh_auto_build: dotnet publish -c Release # auto-build disabled override_dh_auto_install: # install application mkdir -p debian/testapp/opt/testapp install -D -m 755 bin/Release/ubuntu.18.04-x64/publish/* debian/testapp/opt/testapp override_dh_shlibdeps: # shilbdeps disabled override_dh_strip: # strip disabled</span> </pre> <br /> <hr style='width: 50%' /><br /> <br /> 일단, 위의 단계까지는 윈도우에서도 할 수 있습니다. 하지만 이것으로부터 실질적인 패키지를 만들어 주는 dpkg-buildpackage 명령어는 우분투 프로그램이므로 WSL이나 우분투 환경에서 진행해야 합니다.<br /> <br /> 이 글에서는 WSL에서 할 텐데요, 따라서 패키지 구성 파일들을 다음과 같이 WSL 환경으로 복사합니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > $ <span style='color: blue; font-weight: bold'>cp -r /mnt/c/temp/buildroot ./buildroot</span> </pre> <br /> 자, 이제 모든 준비가 끝났습니다. ^^ 패키징을 위한 도구를 다운로드하고,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > // 아래의 툴 설치가 제법 오래 걸립니다. ^^ $ <span style='color: blue; font-weight: bold'>sudo apt install gnupg pbuilder ubuntu-dev-tools apt-file dh-make bzr-builddeb</span> </pre> <br /> dpkg-buildpackage 패키지 명령을 "buildroot" 디렉터리에서 수행해 줍니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > $ <span style='color: blue; font-weight: bold'>cd ./buildroot</span> $ <span style='color: blue; font-weight: bold'>dpkg-buildpackage -b --no-sign</span> dpkg-buildpackage: info: source package testapp dpkg-buildpackage: info: source version 1.0-0ubuntu1 dpkg-buildpackage: info: source distribution bionic dpkg-buildpackage: info: source changed by Test User <testuser@test.com> dpkg-buildpackage: info: host architecture amd64 dpkg-source --before-build . fakeroot debian/rules clean dh clean dh_clean debian/rules build dh build dh_update_autotools_config dh_autoreconf debian/rules override_dh_auto_build make[1]: Entering directory '/home/stjeong/buildroot' dotnet publish -c Release Microsoft (R) Build Engine version 16.10.2+857e5a733 for .NET Copyright (C) Microsoft Corporation. All rights reserved. Determining projects to restore... Restored /home/stjeong/buildroot/testapp.csproj (in 91 ms). testapp -> /home/stjeong/buildroot/bin/Release/testapp.dll Optimizing assemblies for size, which may change the behavior of the app. Be sure to test after publishing. See: https://aka.ms/dotnet-illink testapp -> /home/stjeong/buildroot/bin/Release/ubuntu.18.04-x64/publish/ # auto-build disabled make[1]: Leaving directory '/home/stjeong/buildroot' create-stamp debian/debhelper-build-stamp fakeroot debian/rules binary dh binary dh_testroot dh_prep debian/rules override_dh_auto_install make[1]: Entering directory '/home/stjeong/buildroot' # install application mkdir -p debian/testapp/opt/testapp install -D -m 755 bin/Release/ubuntu.18.04-x64/publish/* debian/testapp/opt/testapp make[1]: Leaving directory '/home/stjeong/buildroot' dh_installdocs dh_installchangelogs dh_perl dh_link dh_strip_nondeterminism dh_compress dh_fixperms dh_missing dh_dwz dwz: debian/testapp/opt/testapp/testapp: .debug_info section not present debian/rules override_dh_strip make[1]: Entering directory '/home/stjeong/buildroot' # strip disabled make[1]: Leaving directory '/home/stjeong/buildroot' dh_makeshlibs debian/rules override_dh_shlibdeps make[1]: Entering directory '/home/stjeong/buildroot' # shilbdeps disabled make[1]: Leaving directory '/home/stjeong/buildroot' dh_installdeb dh_gencontrol dpkg-gencontrol: warning: Depends field of package testapp: substitution variable ${shlibs:Depends} used, but is not defined dh_md5sums dh_builddeb <span style='color: blue; font-weight: bold'>dpkg-deb: building package 'testapp' in '../testapp_1.0-0ubuntu1_amd64.deb'.</span> dpkg-genbuildinfo --build=binary dpkg-genchanges --build=binary >../testapp_1.0-0ubuntu1_amd64.changes dpkg-genchanges: info: binary-only upload (no source code included) dpkg-source --after-build . dpkg-buildpackage: info: binary-only upload (no source included) </pre> <br /> 메시지에 나오듯이, 패키지 파일인 testapp_1.0-0ubuntu1_amd64.deb가 현재 빌드를 수행한 디렉터리(buildroot)의 부모에 생성되었습니다.<br /> <br /> 정말 설치가 되나 볼까요? ^^ 다음과 같이 명령을 입력하면,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > $ <span style='color: blue; font-weight: bold'>cd ..</span> $ <span style='color: blue; font-weight: bold'>sudo dpkg -i testapp_1.0-0ubuntu1_amd64.deb</span> Selecting previously unselected package testapp. (Reading database ... 50171 files and directories currently installed.) Preparing to unpack testapp_1.0-0ubuntu1_amd64.deb ... Unpacking testapp (1.0-0ubuntu1) ... Setting up testapp (1.0-0ubuntu1) ... </pre> <br /> 설치가 되고, rules Makefile에 디렉터리를 구성한 대로 /opt/testapp 하위에 바이너리가 위치한 것을 확인할 수 있습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > $ <span style='color: blue; font-weight: bold'>ls -l /opt/testapp</span> total 20788 drwxr-xr-x 2 root root 4096 Jul 19 18:29 ./ drwxr-xr-x 3 root root 4096 Jul 19 18:29 ../ -rwxr-xr-x 1 root root 21274918 Jul 17 13:20 testapp* $ <span style='color: blue; font-weight: bold'>/opt/testapp/testapp</span> Hello World! </pre> <br /> 와~~~ 멋지군요. ^^<br /> <br /> <hr style='width: 50%' /><br /> <br /> 그런데, 한 가지 궁금한 것은 rules 파일을 이용해 내부에서 직접 빌드한 후 디렉터리를 구성해야 deb 패키지에 바이너리가 들어가는데요, 그냥 미리 빌드된 결과물만 ./buildroot 디렉터리에 구성해 놓으면 안 되는 걸까요? (혹시 방법을 아시는 분은 덧글 부탁드립니다. ^^)<br /> <br /> 참고로 <a target='tab' href='https://medium.com/bluekiri/packaging-a-net-core-service-for-ubuntu-4f8e9202d1e5'>원 글</a>을 보면 하나의 deb 파일에 2개의 배포 패키지를 담는 것을 설명합니다. 또한, systemd를 이용한 데몬(Daemon) 유형의 응용 프로그램을 설치하는 방법도 다룹니다.<br /> <br /> 그리고, 사설 Debian package repository를 운영해 위에서 만든 deb 패키지를 올려 "apt install"로 설치하는 방법도 다루고 있습니다. 나중에 이 부분도 시간 나면 한번 정리해 보겠습니다. ^^<br /> <br /> 마지막으로, 참조 사이트 하나.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > The Debian Archive ; <a target='tab' href='https://www.debian.org/doc/debian-policy/ch-archive.html'>https://www.debian.org/doc/debian-policy/ch-archive.html</a> </pre> </p><br /> <br /><hr /><span style='color: Maroon'>[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]</span> </div>
첨부파일
스팸 방지용 인증 번호
1786
(왼쪽의 숫자를 입력해야 합니다.)