Upgrade to Pro — share decks privately, control downloads, hide ads and more …

個人で出来るWebサービスの作り方(YAPC::ASIA 2013)

koba04
September 20, 2013
19k

個人で出来るWebサービスの作り方(YAPC::ASIA 2013)

個人で出来るWebサービスの作り方(YAPC::ASIA 2013) @koba04

koba04

September 20, 2013
Tweet

Transcript

  1. ࣗݾ঺հ • @koba04 • #1982 • MobileFactory • Perl, JavaScript

    ... • http://about.me/koba04 13೥9݄20೔༵ۚ೔
  2. ٕज़తબ୒ Nginxʁ Amon2ʁ MySQLʁ Redisʁ Apacheʁ Grunt.jsʁ Backbone.jsʁ Chefʁ Vagrantʁ

    Bower.jsʁ sassʁ memcachedʁ Angular.jsʁ supervisorʁ daemontools? Cartonʁ Starletʁ Tengʁ CentOSʁ Ubuntuʁ 13೥9݄20೔༵ۚ೔
  3. ٕज़తબ୒ Nginxʁ Amon2ʁ MySQLʁ Redisʁ Apacheʁ Grunt.jsʁ Backbone.jsʁ Chefʁ Vagrantʁ

    Bower.jsʁ sassʁ memcachedʁ Angular.jsʁ supervisorʁ daemontools? Cartonʁ Starletʁ Tengʁ CentOSʁ Ubuntuʁ ԿΛ࢖͑͹͍͍ͷʁ 13೥9݄20೔༵ۚ೔
  4. ग़དྷΔ͜ͱ͔Βண࣮ʹ 1. Nginx + Starlet(Plack::Builder) + KyotoTycoon 1. Nginx +

    Starlet(Amon2) + MySQL+ memcached Grunt + Backbone.js + Compass 2. KyotoTycoon to Memcached 3. Grunt & CoffeeScript 2. MySQL + memcached to Redis 3. Carton & Bower & CoffeeScript 13೥9݄20೔༵ۚ೔
  5. ެ։͢ΔͨΊͷ؀ڥ • Ϩϯλϧαʔόʔ ... ࣗ༝౓͕ྼΔ • ࣗ୐αʔόʔ ... ӡ༻͕େม(&ిؾ୅) •

    VPS ... rootͰࣗ༝ʹग़དྷΔ͠ɺՁ֨΋Ϧʔζφϒϧ • AWS ... VPSʹൺ΂Δͱߴ͍ɻAWSʹ͍ͭͯͷ஌ࣝ΋ඞཁʹͳΔɻ • Paas ... ͓खܰʹެ։ग़དྷΔ͕ɺPlatform͕ఏڙ͍ͯ͠Δൣғʹ੍ݶ͞ΕΔ ୯७ʹΞϓϦέʔγϣϯΛ1ͭެ։͢Δ͚ͩͳΒɺPaas΋ΞϦ͚ͩͲɺͪΐͬͱ ͨ͠botஔ͍ͨΓɺ࣮ݧ͍ͨ͠ͳΒVPS͕͍͍ɻ ͪΌΜͱӡ༻͍ͨ͠ͳΒ࠷ॳ͔ΒAWSͰ΍Δͷ΋ΞϦ 13೥9݄20೔༵ۚ೔
  6. ެ։͢ΔͨΊͷ؀ڥ • Ϩϯλϧαʔόʔ ... ࣗ༝౓͕ྼΔ • ࣗ୐αʔόʔ ... ӡ༻͕େม(&ిؾ୅) •

    VPS ... rootͰࣗ༝ʹग़དྷΔ͠ɺՁ֨΋Ϧʔζφϒϧ • AWS ... VPSʹൺ΂Δͱߴ͍ɻAWSʹ͍ͭͯͷ஌ࣝ΋ඞཁʹͳΔɻ • Paas ... ͓खܰʹެ։ग़དྷΔ͕ɺPlatform͕ఏڙ͍ͯ͠Δൣғʹ੍ݶ͞ΕΔ ୯७ʹΞϓϦέʔγϣϯΛ1ͭެ։͢Δ͚ͩͳΒɺPaas΋ΞϦ͚ͩͲɺͪΐͬͱ ͨ͠botஔ͍ͨΓɺ࣮ݧ͍ͨ͠ͳΒVPS͕͍͍ɻ ͪΌΜͱӡ༻͍ͨ͠ͳΒ࠷ॳ͔ΒAWSͰ΍Δͷ΋ΞϦ 13೥9݄20೔༵ۚ೔
  7. Nginxͷઃఆ server { listen 80; server_name petatube.koba04.com; location / {

    proxy_pass http://localhost:9001; proxy_set_header X-Real-IP $remote_addr; proxy_set_header Host $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; break; } location ~ .*\.(jpg|gif|png||css|js|ico)$ { root /home/koba04/app/petatube; break; } } https://github.com/koba04/p5-petatube/blob/master/server/development/vagrant/chef/site-cookbooks/ petatube/files/default/nginx/petatube.conf 13೥9݄20೔༵ۚ೔
  8. Nginxͷઃఆ server { listen 80; server_name petatube.koba04.com; location / {

    proxy_pass http://localhost:9001; proxy_set_header X-Real-IP $remote_addr; proxy_set_header Host $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; break; } location ~ .*\.(jpg|gif|png||css|js|ico)$ { root /home/koba04/app/petatube; break; } } 9001portͷ ΞϓϦέʔγϣϯɾαʔόʔʹ ϓϩΩγͯ͠Δ https://github.com/koba04/p5-petatube/blob/master/server/development/vagrant/chef/site-cookbooks/ petatube/files/default/nginx/petatube.conf 13೥9݄20೔༵ۚ೔
  9. Perlͷόʔδϣϯ؅ཧ(anyenv) % git clone https://github.com/riywo/anyenv ~/.anyenv % echo 'export PATH="$HOME/.anyenv/bin:$PATH"'

    >> ~/.your_profile % echo 'eval "$(anyenv init -)"' >> ~/.your_profile % exec $SHELL -l % anyenv install plenv % exec $SHELL -l % plenv install 5.18.1 % plenv global 5.18.1 % plenv install-cpanm % cpanm Carton • anyenvΛ࢖͏ͱ*envܥΛ·ͱΊͯ؅ཧͯ͘͠ΕΔ • https://github.com/riywo/anyenv 13೥9݄20೔༵ۚ೔
  10. Ϟδϡʔϧ؅ཧ(carton) • Carton • https://metacpan.org/module/Carton • ΞϓϦέʔγϣϯຖʹCPANϞδϡʔϧΛ؅ཧͰ͖Δ • ҧ͏؀ڥͰ΋͙͢ʹΞϓϦέʔγϣϯΛಈ͔͢͜ͱ͕Ͱ͖Δ %

    git clone https://github.com/koba04/p5-petatube % cd p5-petatube/app % carton install Installing modules using /home/koba04/p5-petatube/app/cpanfile Successfully installed Sub-Identify-0.04 Successfully installed Module-Functions-2.1.3 : 109 distributions installed Complete! Modules were installed into /home/koba04/p5-petatube/app/local % carton exec plackup -r Watching ./lib app.psgi for file updates. HTTP::Server::PSGI: Accepting connections at http://0:5000/ 13೥9݄20೔༵ۚ೔
  11. Ϟδϡʔϧ؅ཧ(carton) • cpanfile % cat cpanfile requires 'perl', '5.008001'; requires

    'Amon2', '3.85'; : requires 'Coro' ,6.31; requires 'Furl' ,2.18; requires 'Redis' ,1.961; requires 'JSON::XS' ,2.34; requires 'Starlet' ,0.20; requires 'Server::Starter' ,0.15; on 'configure' => sub { requires 'Module::Build', '0.38'; requires 'Module::CPANfile', '0.9010'; }; on 'test' => sub { requires 'Test::More' , '0.98'; requires 'Test::RedisServer', '0.12'; }; on 'develop' => sub { requires 'Proclet', '0.31'; }; % carton install % carton exec plackup ... 13೥9݄20೔༵ۚ೔
  12. WebΞϓϦέʔγϣϯϑϨʔϜϫʔΫ • Amon2 ·ͨ͸ Mojolicious ลΓ͕Αͦ͞͏ (ݸਓతʹ͸Amon2Λ࢖͍ͬͯΔ) • શମ૾Λ೺Ѳग़དྷΔن໛(ιʔεΛಡΊΔ)ͳͷ͕͍͍ %

    tree lib lib !"" PetaTube # !"" Redis.pm # !"" Video.pm # !"" Web # # !"" Dispatcher.pm # # !"" View.pm # # $"" ViewFunctions.pm # $"" Web.pm !"" PetaTube.pm $"" WebService -> ../../submodules/p5-webservice-youtube-lite/lib/WebService https://github.com/koba04/p5-petatube/tree/master/app/lib 13೥9݄20೔༵ۚ೔
  13. σʔλετΞ΁ͷΞΫηε • MySQL (Teng) • O/R Mapperͱͯ͠ͷ໾ׂ͚ͩͰͳ͘ɺTransaction΍઀ଓͷ؅ཧͳͲ໘౗ ͳ෦෼΋΍ͬͯ͘ΕΔ఺Ͱ΋ศར(SQLॻ͘͜ͱ΋ग़དྷΔ) • Memcached

    (Cache::Memcached::Fast) • namespaceɺγϦΞϥΠζͳͲ΋΍ͬͯ͘Εͯ࢖͍΍͍͢ • Redis (Redis.pm) • AUTOLOADͰRedisͷAPI͕࣮૷͞ΕͯΔͷͰɺυΩϡϝϯτʹͳ͍API΋ ࢖͑ͨΓ͢Δ 13೥9݄20೔༵ۚ೔
  14. σʔλετΞ΁ͷΞΫηε (get_callback) • ΩϟογϡΛ࢖͏࣌ʹɺͳ͚Ε͹callbackΛ࣮ߦͯ͠஋Ληοτͭͭ͠ฦ͢ɺ get_callbackؔ਺Λ࡞͓ͬͯ͘ͱ৭ʑศར • RedisͰ΋expireΛ࢖͏͜ͱͰΩϟογϡతͳ࢖͍ํ΋Ͱ͖Δ sub get_callback {

    my $self = shift; my ( $key, $code, $expire ) = @_; my $data = $self->get( $key ); unless ( defined $data ) { $data = $code->(); $self->set($key, $data, $expire); } return $data; } https://github.com/koba04/p5-cdlm/blob/master/lib/CDLM/Cache.pm#L23-L34 13೥9݄20೔༵ۚ೔
  15. σʔλετΞ • MySQL • ӬଓԽ͍ͨ͠σʔλ͕ඞཁͳ࣌ͷୈҰͷબ୒ࢶ • memcached • ֎෦APIͷσʔλΛ࢖͏࣌ͳͲʹ༗ޮɻmemcached͕ͳͯ͘΋ಈ͘ΞϓϦ έʔγϣϯͷઃܭͰ͋Δ͜ͱ͕ඞཁ

    • Redis • ϋογϡͱ͔Ϧετͱ͔ϓϩάϥϚϒϧͳσʔλܕͰอଘ͓ͯ͘͜͠ͱ͕ ग़དྷΔɻϥϯΩϯάͱ͔ͰΑ͘࢖ΘΕͯΔҹ৅ɻݕূதɻ 13೥9݄20೔༵ۚ೔
  16. JavaScript (AltJS) • TypeScript, JSX, CoffeeScriptͳͲ৭ʑ͋Δ͚Ͳɺݸਓతʹ͸CoffeeScriptΛ ؾʹೖͬͯ࢖͍ͬͯΔ • อकੑͷ޲্͕໨తͰ͸ͳ͘ɺؾ࣋Α͘ॻ͚Δ͜ͱΛ໨తʹ͍ͯ͠ΔͷͰ •

    classͷαϙʔτ΍ ޙஔͷif͕࢖͑ͨΓ ɺ=> Ͱͷؔ਺એݴͰ֎ଆͷίϯς Ωετʹग़དྷͨΓ(ϝιου಺ͰΠϕϯτΛઃఆ͢Δ࣌ʹ༗ޮ)... • http://koba04.com/slide/introduction-of-coffeescript/ 13೥9݄20೔༵ۚ೔
  17. JavaScript (CoffeeScript) PetaTube.View.Video = Backbone.View.extend : loadPlayer: -> video =

    @videos.current() # already create video player return @player.loadVideoById video.id if @player # https://developers.google.com/youtube/iframe_api_reference tag = document.createElement 'script' tag.src = "//www.youtube.com/iframe_api" firstScriptTag = document.getElementsByTagName('script')[0] firstScriptTag.parentNode.insertBefore tag, firstScriptTag window.onYouTubeIframeAPIReady = => @player = new YT.Player 'video', height: '425' width: '760' videoId: video.id events: onStateChange: (e) => state = e.data @next() if state is YT.PlayerState.ENDED onError: => @skip() https://github.com/koba04/p5-petatube/blob/master/app/coffee/view/video.coffee 13೥9݄20೔༵ۚ೔
  18. JavaScript (Backbone.js or Angular.js) Backbone.js Angular.js ࠷΋Α͘࢖ΘΕͯΔϑϨʔϜϫʔΫͰ೔ຊޠʹΑΔ ৘ใ΋ଟ͍ ೔ຊޠʹΑΔ৘ใ͸͋·Γଟ͘ͳ͍ JavaScriptΛϞσϧ΍Ϗϡʔʹ͏·͘ߏ଄Խͯ͠ॻ͖

    ΍ͯ͘͘͢͠ΕΔϑϨʔϜϫʔΫ jQuery΍underscoreͷศརػೳ͸࢖͑Δ͕ɺָʹॻ͚ ΔͨΊͷϑϨʔϜϫʔΫͰ͸ͳ͍ ൺֱతࣗ༝ͳͷͰಋೖ͸͠΍͍͢ ໎ͬͨΒͱΓ͋͑ͣBackbone.jsʹ͓͚ͯ͠͹ؒҧ͍ ͳͦ͞͏ ଟػೳͰɺWebΞϓϦέʔγϣϯ։ൃ͢Δͱ͖ʹඞ ཁͦ͏ͳػೳ͸Ұ௨ΓೖͬͯΔ JSON APIͷ݁ՌΛදࣔ͢ΔΑ͏ͳ୯७ͳΞϓϦέʔ γϣϯ͸΋ͷ͘͢͝؆୯ʹॻ͚Δ ಠࣗͷ֓೦΋ଟֶ͘शίετ͸ߴ͍͚Ͳɺ׳ΕΔͱ ؾ࣋ͪΑ͘ॻ͚Δ ςετΛॻͨ͘Ίͷ࢓૊Έ΋͋ͬͯ؆୯ʹςετΛ ॻ͚Δ ModelɺViewΛEventΦϒδΣΫτʹΑΔΦϒβʔό ʔύλʔϯΛ༻͍ͯ࿈ܞ͞ΕͯɺςϯϓϨʔτΛϨϯ μϦϯά͢Δ ControllerΫϥεʹϩδοΫΛॻ͍ͯɺ$scopeΦϒδ ΣΫτʹΑΓɺHTMLΛ֦ுͨ͠Viewʹରͯ͠૒ํ޲ ͷσʔλόΠϯσΟϯάΛߦ͏ DI 13೥9݄20೔༵ۚ೔
  19. JavaScript (Backbone.js) • PetaTubeͰ΋࠾༻ % tree !"" app.coffee !"" collection

    # !"" pages.coffee # $"" videos.coffee !"" model # !"" page.coffee # $"" video.coffee $"" view !"" popular.coffee !"" search.coffee $"" video.coffee https://github.com/koba04/p5-petatube/tree/master/app/coffee 13೥9݄20೔༵ۚ೔
  20. JavaScript (Backbone.js) • Viewͷྫ PetaTube.View.Video = Backbone.View.extend play : ->

    video = @videos.current() if video.get('title') @$el.find("#video-info").text(video.get('title')) $('title').text(video.get('title') + "(PetaTube)") else video.fetch success: => @$el.find("#video-info").text video.get('title') $('title').text "#{video.get('title')}(PetaTube)" @loadPlayer() tmpl = $('#tmpl-button').html() $panel = _.template tmpl, current: @videos.currentIndex + 1 total: @videos.length @$el.find("#video-panel").html $panel @$el.show() https://github.com/koba04/p5-petatube/blob/master/app/coffee/view/video.coffee 13೥9݄20೔༵ۚ೔
  21. JavaScript (Angular.js) <html ng-app> <head> <script src="lib/angular/angular.js"></script> <script> function HogeCtrl($scope)

    { $scope.frameworks = ["Backbone.js", "Angular.js", "Ember.js"]; } </script> </head> <body ng-controller="HogeCtrl"> <ul> <li ng-repeat="framework in frameworks">{{framework}}</li> </ul> </body> </html> • ࣮ࡍʹΞϓϦͰ࢖ͬͨΈͨ࿩ͳͲ͸ԼͷεϥΠυΛ • http://koba04.com/slide/get-started-angularjs/ 13೥9݄20೔༵ۚ೔
  22. Grunt • node੡ͷTask Runner • http://gruntjs.com/ • coffeescript, scssͷίϯύΠϧ΍uglify, concatɺlivereload·ͰϓϥάΠϯ

    Λ࢖͏͜ͱͰઃఆॻ͚ͩ͘Ͱ؆୯ʹ࢖͏͜ͱ͕ग़དྷΔ • GruntʹϑΝΠϧΛwatchͤͯ͞coffeescript΍scssͷίϯύΠϧΛ͢Δ͜ͱ ͰίϯύΠϧΛҙࣝͤͣʹcoffeescript΍scssΛ࢖͑Δ 13೥9݄20೔༵ۚ೔
  23. Grunt module.exports = (grunt) -> "use strict" grunt.initConfig pkg: grunt.file.readJSON

    "package.json" watch: coffee: files: ["src/coffee/**/*.coffee"] tasks: ["coffee2js"] coffee: compile: files: 'htdocs/js/<%= pkg.name %>.js': 'src/coffee/**/*.coffee' uglify: dist: src: "htdocs/js/<%= pkg.name %>.js", dest: "htdocs/js/<%= pkg.name %>.min.js" # load grunt plugings grunt.loadNpmTasks "grunt-contrib-watch" grunt.loadNpmTasks "grunt-contrib-uglify" grunt.loadNpmTasks 'grunt-contrib-coffee' # tasks grunt.registerTask "coffee2js", ["coffee", "uglify"] https://github.com/koba04/p5-petatube/blob/master/app/Gruntfile.coffee 13೥9݄20೔༵ۚ೔
  24. Bower • Twitterࣾ੡ͷϑϩϯτΤϯυ༻ͷύοέʔδϚωʔδϟ • http://bower.io/ • jQuery΍BackboneɺAngularɺunderscoreͳͲϑϩϯτΤϯυͰ࢖͏ϥΠ ϒϥϦͷґଘؔ܎Λ؅ཧͯ͘͠ΕΔ • CDNʹஔ͍ͯ͋ΔϥΠϒϥϦΛ࢖͏৔߹͸ෆཁ

    • Ωϟογϡ΍ಉ࣌઀ଓ਺Λߟ͑ΔͱɺCDNʹஔ͍ͯ͋Δ΋ͷ͕͋ΔͳΒ ͦͬͪΛ࢖͓ͬͯ͘ํ͕͍͍͔΋ʢΦϑϥΠϯͰ։ൃ͠ͳ͍ͳΒʣ 13೥9݄20೔༵ۚ೔
  25. Bower • bower.json ࡞ͬͯ bower install ͢Δͱɺࢦఆͷ৔ॴ(σϑΥϧτ bower_components)ʹࢦఆόʔδϣϯͷϥΠϒϥϦ͕Πϯετʔϧ͞ΕΔ % cat

    bower.json { "name": "p5-petatube", "version": "0.0.2", "main": "statis/js/petatube.js", "ignore": [ "**/.*", "node_modules", "bower_components", "test", "tests" ], "dependencies": {}, "devDependencies": { "jquery": "~2.0.3", "backbone": "~1.0.0", "underscore": "~1.5.1" } } https://github.com/koba04/p5-petatube/blob/master/app/bower.json 13೥9݄20೔༵ۚ೔
  26. CSS(Compass) • CompassΛ࢖ͬͯɺScssͷه๏ͰૉͷCSS͔Βঃʑʹɺม਺ɺωετɺmixin ͳͲΛ࢖ͬͯϓϩάϥϚϒϧʹॻ͍͍ͯ͘ͷ͕͍͍ @import "compass/reset"; @import "compass/css3"; $main-color: #B65F58;

    $highlight-color: #76231D; $base-color: #EED4D2; @mixin line-bottom($op1: .2, $op2: .3){ border-bottom: 1px solid rgba(0, 0, 0, $op1); @include box-shadow(rgba(255, 255, 255, $op2) 0 1px 0); } html { height: 100%; width: 100%; a { font-weight: bold; text-decoration: none; } 13೥9݄20೔༵ۚ೔
  27. ։ൃ؀ڥ(Proclet) • kazeburo͞Μ࡞ͷϓϩηε؅ཧϞδϡʔϧ • https://metacpan.org/module/Proclet • redis, plackup, grunt watchͳͲΞϓϦέʔγϣϯ։ൃʹඞཁͳϓϩηεΛί

    ϚϯυҰͭͰશ෦্ཱͪ͛Δ͜ͱ͕ग़དྷΔ • ϩά΋৭෼͚͞Εͯ·ͱΊͯݟΕΔͷͰͱͯ΋ศརʂ • HomebrewͳͲͰMiddlewareͷ؅ཧΛ͢Δඞཁ͸͋Δ͚ͲɺखܰʹΞϓϦ έʔγϣϯͷ։ൃΛग़དྷΔΑ͏ʹͳͬͯΦεεϝɻ 13೥9݄20೔༵ۚ೔
  28. ։ൃ؀ڥ(Proclet) use strict; use warnings; use Proclet::Declare; env( PLACK_ENV =>

    'development', LM_COLOR => 1, ); service('app', 'carton exec plackup -r app.psgi'); service('grunt', 'grunt watch'); service('redis', 'redis-server ../server/development/proclet/redis.conf'); color; run; https://github.com/koba04/p5-petatube/blob/master/app/start_develop 13೥9݄20೔༵ۚ೔
  29. ։ൃ؀ڥ(Ծ૝Ϛγϯ) • Vagrant ... VirtualBoxͳͲͷԾ૝ϚγϯΛίϚϯυϥΠϯ͔Βૢ࡞ग़དྷΔ • http://www.vagrantup.com/ • Chef (Knife

    Solo) ... ؀ڥߏஙΛRubyͷίʔυϕʔεͰߦ͏ࣄ͕Ͱ͖Δ • http://www.opscode.com/chef/ • serverspec ... αʔόʔͷઃఆɺߏ੒ͷςετRSpecͰॻ͘͜ͱ͕ग़དྷΔ • http://serverspec.org/ 13೥9݄20೔༵ۚ೔
  30. ։ൃ؀ڥ(Ծ૝Ϛγϯ) • Chef(Knife Solo)ɺserverspecͱ͔Ͱ࡞Δ·Ͱ΍Γͩ͢ͱ݁ߏେม • αʔόʔ؀ڥΛίʔυॻ͍ͯςετͯ͠Λ܁Γฦͯ͠࡞ͬͯͷ͸݁ߏָ͠ ͍(·ͣ͸bash_resource͔Β) • ؀ڥΛηοτΞοϓͯ͋͠ΔԾ૝ϚγϯΛ࡞ΓɺͦΕΛ࢖͍·Θ͘͢Β͍ͳΒ ൺֱతखܰʹग़དྷΔ

    • खݩͷϚγϯʹ৭ʑΠϯετʔϧͨ͘͠ͳ͔ͬͨΓɺ৭Μͳ؀ڥͰಈ͔ͨ͠ ͍࣌ʹ͸vagrantͰԾ૝Ϛγϯ࡞ͬͯ΍Δͷ͸Αͦ͞͏ खؒ͸ֻ͔Δ͚Ͳ ίϚϯυ1ͭͰApplication͕ ىಈͨ͠ঢ়ଶͷԾ૝ϚγϯΛ ࡞ΕΔͷ͸݁ߏײಈ͢Δ 13೥9݄20೔༵ۚ೔
  31. ຊ൪؀ڥ(supervisor) • A Process Control System. • http://supervisord.org/ • ΞϓϦ͚ͩͰͳ͘nginx΍redisͳͲϛυϧ΢ΣΞ΋supervisorͰ؅ཧͯ͠Δ

    • ϓϩηε͕མͪͯ΋ࣗಈతʹ࠶ىಈͯ͘͠ΕΔͷͰݸਓͰͷ։ൃʹ༏͍͠ • daemontools΋͋Δ͚Ͳɺݸਓతʹͪ͜Βͷํ͕Θ͔Γ΍͔ͬͨ͢ͷͰ࢖ ͬͯΔ 13೥9݄20೔༵ۚ೔
  32. ຊ൪؀ڥ(supervisor) [program:petatube] user=koba04 command=sh /home/koba04/petatube/server/production/supervisor/petatube.sh redirect_stderr=true stdout_logfile=/var/log/petatube/app.log autostart=true autorestart=true #!/bin/sh

    cd /home/koba04/petatube/app exec /home/koba04/perl5/perlbrew/perls/perl-5.18.1/bin/carton exec -- start_server --port=9001 \ -- plackup -s Starlet -E production \ --max-workers=3 \ /home/koba04/petatube/app/app.psgi https://github.com/koba04/p5-petatube/blob/master/server/production/supervisor/petatube.conf https://github.com/koba04/p5-petatube/blob/master/server/production/supervisor/petatube.sh 13೥9݄20೔༵ۚ೔