"Enter"a basıp içeriğe geçin

Electron ile arkaplan servisi başlatmak

Merhabalar, Electron ile masaüstü uygulaması geliştirirken root yetkisine sahip olup sistemde tekrar eden işlemler yapmanız gerekebilir veya electron uygulamanız kapansa bile bazı işlemlerin hala yapılmasını isteyebilirsiniz. Bugün tamda bu konuya yönelik basit bir örnek hazırladım.

Temelde mantığımız masaüstünde bir api servisi başlatıp bu servise root yetkisi verip uygulama açılır açılmaz başlaması sağlamak.

Öncelikle kendimize bir çalışma ortamı hazırlayalım.Electronun quick-start appi ile başlayalım.

# Clone the repository
git clone https://github.com/electron/electron-quick-start
# Go into the repository
cd electron-quick-start
# Install dependencies
npm install
# Run the app
npm start

Daha sonra proje ana dizinimize services adında bir klasör açalım.Bu klasöre background servisimizin bir executable halini atıyoruz. Ben daha önce go ile oluşturduğum bir servisi build edip klasör içine atıyorum.Siz kendi oluşturdunuz serviside kullanabilirsiniz.

Peki bu servis ne yapıyor. Onada bir açıklık getirelim

Örnek Go Servisi

Servisin amacı belirli aralıklarla temp klasörü içine bir text dosyası atmak. Ben go build ile uğraşamam derseniz şuradan indirebilirsiniz.

package main

import (
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"time"
	"net/http"

)
func main() {
	http.HandleFunc("/",  handler)
	ticker := time.NewTicker(1 * time.Second)
	go func() {
		for t := range ticker.C {
			_ = t
			fmt.Println("Hello I'm a service")
			WriteTmp()
		}
	}()
	time.Sleep(10 *time.Second)
	ticker.Stop()
	http.ListenAndServe(":4576", nil)
}

func WriteTmp() {
	tmpFile, err := ioutil.TempFile(os.TempDir(), "karaboga-")
	if err != nil {
		log.Fatal( err)
	}
	text := []byte("This is a background service -- barankaraboga.com")
	if _, err = tmpFile.Write(text); err != nil {
		log.Fatal(err)
	}

	if err := tmpFile.Close(); err != nil {
		log.Fatal(err)
	}
}

func handler(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "Hello this is your temp dir: %s", os.TempDir())
}

Servisi root olarak başlatmak

Yukarıdaki örnek servisi build ettikten sonra electron projemize geri dönelim. Servisimizin root olarak başlatmak için kullanıcıdan izin almamız gerekiyor. Bunun için sudo-prompt kullanabiliriz. Sudo-promptu projemize ekleyelim.

npm install sudo-prompt

Servisimizi başlatmadan önce bu portta bir servis çalışıyor mu diye bir kontrole edelim. Port check için javascriptte şu methodu kullanıyorum:

var net = require("net");
        
portInUse(port, callback) {
            var server = net.createServer(function(socket) {
                socket.write("Echo server\r\n");
                socket.pipe(socket);
            });

            server.listen(port, "127.0.0.1");
            server.on("error", function(e) {
                callback(true);
            });
            server.on("listening", function(e) {
                server.close();
                callback(false);
            });
        },

Fonksiyonlarımızı ben preload.js dosyası içine ekliyorum. Ama siz uygulamanızın hangi statede iken başlatmak istiyorsanız fonksiyonları oraya taşıyabilirsiniz.

your_service_path kısımlarını kendi servis pathiniz ile değiştirmeyi unutmayın.

var net = require("net");
var sudo = require("sudo-prompt");

window.addEventListener('DOMContentLoaded', () => {
  let service_path = ""

  if (process.platform === "win32") {
    service_path = "your_windows_service_path"
  } else if (process.platform === "linux") {
    service_path = "your_linux_service_path"
  } else {
    service_path ="your_other_service_path"
  }


  portInUse(4576, function (returnValue) {
    if (!returnValue) {
      sudo.exec(service_path, {
          name: "Karaboga",
        },
        function (error, stdout, stderr) {
          if (error) {
            console.log(error)
          }
        }
      );
    } else {
      console.log("Port is already in use!")
    }
  });
})

function portInUse(port, callback) {
  var server = net.createServer(function (socket) {
    socket.write("Echo server\r\n");
    socket.pipe(socket);
  });

  server.listen(port, "127.0.0.1");
  server.on("error", function (e) {
    callback(true);
  });
  server.on("listening", function (e) {
    server.close();
    callback(false);
  });
}

Daha sonra

npm start

diyerek projemizi çalıştıralım. Karşımızda şu şekilde bir ekran görmemiz gerekiyor. sudo-prompt cross platform çalıştığı içinde windows mac ve linuxdada benzer promtları almış oluyoruz.

bu şekilde arkaplan servisimizi root olarak başlatmış olduk. Artık uygulama içinden localhost:4576 ile iletişime geçerek sistem üzerinde root olarak işlem yapabiliriz. Bunuda servisinizde bir endpoint açarak gerçekleştirebilirsiniz.

Uygulamayı bir defa daha açtımız da bu sefer prompt çıkmayacaktır çünkü o port üzerinde zaten arkaplan servisimiz çalışıyor.Uykuya geçme, force quit durumları handle eden ayrı bir yazı yazmayı planlıyorum. Umarım electron uygulamalarına kendi arkaplan servislerini eklemek isteyenlere akıllarında bir fikir oluşturabilmişimdir.

Peki neler yapılabilir?

Nerdeyse tüm programlama dilleri ile executeable bir formatta çıktı alabilirsiniz. Mesela nodejs için pkg’yi öneririm. Root yetkisi ile başlattığınız uygulama ile electrondan bağımsız işlemler yaptırabilirsiniz.Örnek olarak electron uygulaması kapandıktan sonra uygulama ile alakalı local bir backup almanız gerekiyorsa bu sizin için iyi bir çözüm olabilir.

Nelere dikkat etmeli ?

Unutmayın yazdınız serviside cross platform yazmanız gerekiyor, Bu yüzden build alırken platformlara görede build almayı unutmayın.

Production’a çıkarken eğer electron builder kullanıyorsanız extraResource tanımlayıp, sudo-exec’e doğru bir path verdiğinizden emin olun.

MacOS için olan buildlerde artık servisinizide xcode ile sign etmeniz gerekiyor. Yoksa background servisiniz çalışmayabilir

Bir cevap yazın

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir