делать действия в конце исполнения - PullRequest
6 голосов
/ 06 декабря 2011

У меня есть http-сервер (запущен с использованием http.Handle), и я хотел бы выполнить некоторые операции.

Как я могу это сделать (на Linux)? Можно ли выполнять эти операции в случае ctrl-C?

Я не знаком с сигналами Unix, поэтому ответ может быть тривиальным.

Ответы [ 3 ]

17 голосов
/ 21 июня 2012

Используя ответ kostix, я создал этот код (теперь адаптированный для Go1), чтобы перехватить сигнал прерывания и выполнить некоторые операции перед выходом:

go func() {
    sigchan := make(chan os.Signal, 10)
    signal.Notify(sigchan, os.Interrupt)
    <-sigchan
    log.Println("Program killed !")

    // do last actions and wait for all write operations to end

    os.Exit(0)
}()

// start main program tasks
4 голосов
/ 06 декабря 2011

Вы можете подписаться на сигналы TERM и INT, используя пакет signal .Но обратите внимание, что эти сигналы отправляются только тогда, когда процесс явно прерван;нормальный выход (инициируемый самим процессом) не требует каких-либо сигналов.Я думаю, что для нормального выхода просто сделайте что-нибудь в основной подпрограмме (которая должна порождать рабочие программы и затем ждать их).

Чтение man 7 signal для получения более общей информации о сигналах POSIX.

0 голосов
/ 25 декабря 2017

Я полагаю, что автор заинтересован не только в Ctrl + C и предлагает более широкое решение для Linux (для сигналов Windows см. x / sys / windows ):

package main

import (
  "os"
  "os/signal"
  "syscall"
  "fmt"
)

func getFireSignalsChannel() chan os.Signal {

  c := make(chan os.Signal, 1)
  signal.Notify(c,
    // https://www.gnu.org/software/libc/manual/html_node/Termination-Signals.html
    syscall.SIGTERM, // "the normal way to politely ask a program to terminate"
    syscall.SIGINT, // Ctrl+C
    syscall.SIGQUIT, // Ctrl-\
    syscall.SIGKILL, // "always fatal", "SIGKILL and SIGSTOP may not be caught by a program"
    syscall.SIGHUP, // "terminal is disconnected"
  )
  return c

}

func exit() {
  syscall.Kill(syscall.Getpid(), syscall.SIGTERM)
}

func main() {

  exitChan := getFireSignalsChannel()
  input, err := os.Open("input.txt")
  if err != nil {
    panic(err)
  }
  defer input.Close()
  <-exitChan
  fmt.Println("Exiting!")
  return
  // All main deferreds executed here even in case of panic.
  // Non-main deferreds are not executed here.

}

P.S. Ни один из сигналов не обрабатывает os.Exit.

При такой конфигурации на Ctrl + C или при получении другого сигнала программа переместит os.Signal в канал exitChan, что разблокирует операцию <-exitChan, а функция main продолжит выполнение на последние строки, затем возврат, затем выполнение отложенных функций.

Неосновные отсрочки

Для неосновных отсрочек вы можете:

  1. Использование https://github.com/tebeka/atexit
  2. Перемещение важных ресурсов в глобальный массив и освобождение их в основном отсроченном. Это решение не идеально, если вы не используете транзакцию: 1) создать ресурс, 2) добавить в массив, - который не должен прерываться при выходе. Также, я полагаю, должен быть предоставлен не одновременный доступ для чтения и записи к срезу.
...