Run as a daemon or service: Difference between revisions

m
→‎{{header|Wren}}: Minor tidy and rerun
m (→‎{{header|Wren}}: Minor tidy and rerun)
 
(7 intermediate revisions by 4 users not shown)
Line 11:
==={{header|FreeBASIC}}===
{{trans|QB64}}
<langsyntaxhighlight lang="freebasic">ScreenLock()
Open "c:\Users\Default\Documents\myDaemon.log" For Append As #1
'Open "myDaemon.log" For Append As #1 'Ruta de archivo relativa para la salida // Relative file path for the output
Line 22:
Close #1 'Cierra el archivo previamente abierto para escritura // Close the file previously open for writing
ScreenUnlock()
End</langsyntaxhighlight>
 
==={{header|QB64}}===
<langsyntaxhighlight lang="freebasic">'Metacommands and Statements for closing console or window
'' The following line is double commented ('') as some metacommands still execute even when singularly commented (')
''$Console 'Closes the console but does not close the main window, used for whole program run
Line 40:
Next i%
Close #1 'Closes the file previously opened for writing
System</langsyntaxhighlight>
{{out}}
<pre>09:02:23 - Running
Line 54:
The task also wants to redirect stdout. This program does so with [http://netbsd.gw.com/cgi-bin/man-cgi?dup2+2+NetBSD-current dup2(2)]. Had we wanted to directly write to a file, we could open the file with <code>file = fopen(argv[1], "a")</code>, and write to ''file'' instead of ''stdout''.
 
<langsyntaxhighlight lang="c">#include <err.h>
#include <errno.h>
#include <fcntl.h>
Line 105:
sleep(1); /* Can wake early or drift late. */
}
}</langsyntaxhighlight>
 
<pre>$ make dumper
Line 123:
{{libheader|go-daemon}}
{{works with|Ubuntu 16.04}}
<langsyntaxhighlight lang="go">package main
 
import (
Line 174:
 
work()
}</langsyntaxhighlight>
 
{{out}}
Line 196:
{{trans|Python}}
This is a direct translation of the Python Posix version.
<langsyntaxhighlight Nimlang="nim">import os, posix, strutils
 
let pid = fork()
Line 222:
while now() < t + initDuration(seconds = 10):
echo "timer running, $# seconds".format((now() - t).inSeconds)
sleep(1000)</langsyntaxhighlight>
 
{{out}}
Line 239:
=={{header|PARI/GP}}==
GP scripts cannot run in this fashion directly, but can be compiled into PARI code with <code>gp2c</code>. PARI code, whether from <code>gp2c</code> or not, can be run as a daemon just as [[#C|C]] would be.
 
=={{header|Perl}}==
First off, start with a standalone script and let's call it "count.pl"
<syntaxhighlight lang="perl"># 20211217 Perl programming solution
 
use strict;
use warnings;
 
use IO::Handle;
use File::Temp qw/ tempfile tempdir /;
 
my ($fh, $tempfile) = tempfile();
my $count = 0;
 
open $fh, '>', $tempfile or die;
 
print "\n\nOutput goes to $tempfile\n";
 
while (1) {
sleep 1;
print $fh "Sheep number ",$count++," just leaped over the fence ..\n";
$fh->flush();
}</syntaxhighlight>
Make sure it works and then we can control/run it in daemon mode with another script
<syntaxhighlight lang="perl">use warnings;
use strict;
 
use Daemon::Control;
 
exit Daemon::Control->new(
name => 'Counter daemon',
program => '/home/hkdtam/count.pl',
pid_file => '/tmp/counter.pid',
)->run;</syntaxhighlight>
{{out}}
<pre>
./daemon.pl status
Counter daemon [Not Running]
./daemon.pl start
Counter daemon [Started]
 
Output goes to /tmp/5wHmHKu4fN
 
./daemon.pl status
Counter daemon [Running]
tail -3 /tmp/5wHmHKu4fN
Sheep number 76 just leaped over the fence ..
Sheep number 77 just leaped over the fence ..
Sheep number 78 just leaped over the fence ..
cat /tmp/counter.pid
32178
./daemon.pl restart
Counter daemon [Stopped]
Counter daemon [Started]
 
Output goes to /tmp/ttTTS4oGY_
 
tail -3 /tmp/ttTTS4oGY_
Sheep number 32 just leaped over the fence ..
Sheep number 33 just leaped over the fence ..
Sheep number 34 just leaped over the fence ..
cat /tmp/counter.pid
32188
./daemon.pl stop
Counter daemon [Stopped]
./daemon.pl status
Counter daemon [Not Running]
cat /tmp/counter.pid
cat: /tmp/counter.pid: No such file or directory
</pre>
 
=={{header|Phix}}==
Assuming this task is simply "a program that can write to stdout(/stderr) or a file".<br>
In some cases free_console() may help, should an attached console have been incorrectly created in the first place.<br>
Be warned however that some methods of invocation and (obviously) console capture may die horribly when that is invoked inappropriately.<br>(Specifically, you can spend an awful long time waiting for a message or signal, from an agent that has just been surrepticiously murdered.)<br>
Phix does not have an implicit stdout, instead (eg) printf(1,fmt,srgsargs) writes
to stdout, whereas printf(fn,fmt,args) writes to some previously opened fn.<br>
Of course there is nothing at all to stop fn from being set to 1 for stdout, or 2 for stderr.<br>
It is also strongly against the core philosophy of Phix to have or permit anything that would somehow make printf(1,x) do something it does not look like it should be doing, especially given printf(fn,x) has no such ambiguity. Not having to change your code may sound dandy, not being able to tell what your code is doing by looking at it, isn't.
<!--<langsyntaxhighlight Phixlang="phix">(phixonlinenotonline)-->
<span style="color: #008080;">without</span> <span style="color: #008080;">javascript_semantics</span>
<span style="color: #008080;">include</span> <span style="color: #004080;">timedate</span><span style="color: #0000FF;">.</span><span style="color: #000000;">e</span>
Line 257 ⟶ 327:
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #7060A8;">close</span><span style="color: #0000FF;">(</span><span style="color: #000000;">fn</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- [close(1) quietly does nothing]</span>
<!--</langsyntaxhighlight>-->
{{out}}
<small>(When fn is 1, or the content of log.txt when it is not.)</small>
Line 269 ⟶ 339:
 
=={{header|PicoLisp}}==
<langsyntaxhighlight PicoLisplang="picolisp">(unless (fork)
(out "file.log"
(println *Pid) # First write the daemon's PID to the file
Line 278 ⟶ 348:
(bye) ) # Child terminates after one hour
 
(bye) # Parent terminates immediately</langsyntaxhighlight>
 
=={{header|Pike}}==
Line 284 ⟶ 354:
if the first argument is "daemon" the program will be restarted with stdout redirected to "foo".
 
<langsyntaxhighlight Pikelang="pike">int main(int argc, array argv)
{
if (sizeof(argv)>1 && argv[1] == "daemon")
Line 299 ⟶ 369:
sleep(0.1);
}
}</langsyntaxhighlight>
 
=={{header|Python}}==
<langsyntaxhighlight lang="python">
#!/usr/bin/python3
import posix
Line 332 ⟶ 402:
print("timer running, %s seconds" % str(time.time() - t))
time.sleep(1)
</syntaxhighlight>
</lang>
 
=={{header|Racket}}==
<langsyntaxhighlight lang="racket">
#lang racket
(require ffi/unsafe)
Line 341 ⟶ 411:
(with-output-to-file "/tmp/foo"
(λ() (for ([i 10]) (displayln (random 1000)) (flush-output) (sleep 1))))
</syntaxhighlight>
</lang>
 
=={{header|Raku}}==
(formerly Perl 6)
<syntaxhighlight lang="raku" perl6line># Reference:
# https://github.com/hipek8/p6-UNIX-Daemonize/
 
Line 361 ⟶ 431:
sleep(1);
spurt $output, DateTime.now.Str~"\n", :append;
}</langsyntaxhighlight>
{{out}}<pre>root@ubuntu:~# su - david
david@ubuntu:~$ ./dumper.p6
Line 414 ⟶ 484:
=={{header|Sidef}}==
When the "daemon" argument is specified, a fork of the program is created with its STDOUT redirected into the file "foo.txt", and the main process is exited.
<langsyntaxhighlight lang="ruby">var block = {
for n in (1..100) {
STDOUT.say(n)
Line 431 ⟶ 501:
 
STDERR.say("Normal mode")
block.run</langsyntaxhighlight>
 
=={{header|Smalltalk}}==
{{works with |Smalltalk/X}}
<langsyntaxhighlight lang="smalltalk">#! /usr/bin/env stx --script
(pid := OperatingSystem fork) == 0 ifTrue:[
Stdin close.
Line 450 ⟶ 520:
Stdout showCR: e'forked new process pid={pid}; now exiting'.
OperatingSystem exit:0
]</langsyntaxhighlight>
{{out}}
<pre>bash-3.2$ ./daemon.st
Line 467 ⟶ 537:
Tcl doesn't come with tools for converting the process into a daemon, but can build them easily enough. Here's the BSD daemon function mapped into a Tcl command in a package.
{{libheader|Critcl}}
<langsyntaxhighlight lang="tcl">package provide daemon 1
package require critcl
 
Line 480 ⟶ 550:
}
return TCL_OK;
}</langsyntaxhighlight>
These tools can then be used to solve this task:
<langsyntaxhighlight lang="tcl">### Command line argument parsing
if {$argc < 1} {
puts "usage: $argv0 file ?message...?"
Line 501 ⟶ 571:
proc every {ms body} {eval $body; after $ms [info level 0]}
every 1000 {puts "[clock format [clock seconds]]: $message"}
vwait forever</langsyntaxhighlight>
On Windows, there is a commercial extension to Tcl which allows a script to be installed as a service. Such a script would be much like the one above, but without the daemonization section as that has become a property of the runtime.
 
=={{header|Wren}}==
{{libheader|Wren-date}}
An embedded program but the actual daemon is of course the C host even though the process is orchestrated by the Wren code which handles any errors and prints the time every second to the file.
 
The following script is based on the C example though modified a little to run on Ubuntu 22.04.
<syntaxhighlight lang="wren">/* Run_as_a_daemon_or_service.wren */
 
import "./date" for Date
 
var O_WRONLY = 1
var O_APPEND = 1024
var O_CREAT = 64
 
var STDOUT_FILENO = 1
 
class C {
foreign static fileName
 
foreign static open(pathName, flags, mode)
 
foreign static daemon(nochdir, noclose)
 
foreign static redirectStdout(oldfd, newfd)
 
foreign static close(fd)
 
foreign static time
 
foreign static sleep(seconds)
}
 
// gets a Date object from a Unix time in seconds
var UT2Date = Fn.new { |ut| Date.unixEpoch.addSeconds(ut) }
 
Date.default = "ddd| |mmm| |dd| |hh|:|MM|:|ss| |yyyy" // default format for printing
 
// open file before becoming a daemon
var fd = C.open(C.fileName, O_WRONLY | O_APPEND | O_CREAT, 438)
if (fd < 0) {
System.print("Error opening %(C.fileName)")
return
}
 
// become a daemon
if (C.daemon(0, 0) < 0) {
System.print("Error creating daemon.")
return
}
 
// redirect stdout
if (C.redirectStdout(fd, STDOUT_FILENO) < 0) {
System.print("Error redirecting stdout.")
return
}
 
// close file
if (C.close(fd) < 0) {
System.print("Error closing %(C.fileName)")
return
}
 
// dump time every second
while (true) {
System.print(UT2Date.call(C.time))
C.sleep(1)
}</syntaxhighlight>
<br>
We now embed this in the following C program, compile and run it.
<syntaxhighlight lang="c">/* gcc Run_as_a_daemon_or_service.c -o dumper -lwren -lm */
 
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include "wren.h"
 
char *fileName;
 
void C_fileName(WrenVM* vm) {
wrenSetSlotString(vm, 0, fileName);
}
 
void C_open(WrenVM* vm) {
const char *pathName = wrenGetSlotString(vm, 1);
int flags = (int)wrenGetSlotDouble(vm, 2);
mode_t mode = (mode_t)wrenGetSlotDouble(vm, 3);
int fd = open(pathName, flags, mode);
wrenSetSlotDouble(vm, 0, (double)fd);
}
 
void C_daemon(WrenVM* vm) {
int nochdir = (int)wrenGetSlotDouble(vm, 1);
int noclose = (int)wrenGetSlotDouble(vm, 2);
int d = daemon(nochdir, noclose);
wrenSetSlotDouble(vm, 0, (double)d);
}
 
void C_redirectStdout(WrenVM* vm) {
int oldfd = (int)wrenGetSlotDouble(vm, 1);
int newfd = (int)wrenGetSlotDouble(vm, 2);
newfd = dup2(oldfd, newfd);
wrenSetSlotDouble(vm, 0, (double)newfd);
}
 
void C_close(WrenVM* vm) {
int fd = (int)wrenGetSlotDouble(vm, 1);
int ret = close(fd);
wrenSetSlotDouble(vm, 0, (double)ret);
}
 
void C_time(WrenVM* vm) {
time_t t = time(NULL);
wrenSetSlotDouble(vm, 0, (double)t);
}
 
void C_sleep(WrenVM* vm) {
unsigned int seconds = (unsigned int) wrenGetSlotDouble(vm, 1);
unsigned int ret = sleep(seconds);
wrenSetSlotDouble(vm, 0, (double)ret);
}
 
WrenForeignMethodFn bindForeignMethod(
WrenVM* vm,
const char* module,
const char* className,
bool isStatic,
const char* signature) {
if (strcmp(module, "main") == 0) {
if (strcmp(className, "C") == 0) {
if (isStatic && strcmp(signature, "fileName") == 0) return C_fileName;
if (isStatic && strcmp(signature, "open(_,_,_)") == 0) return C_open;
if (isStatic && strcmp(signature, "daemon(_,_)") == 0) return C_daemon;
if (isStatic && strcmp(signature, "redirectStdout(_,_)") == 0) return C_redirectStdout;
if (isStatic && strcmp(signature, "close(_)") == 0) return C_close;
if (isStatic && strcmp(signature, "time") == 0) return C_time;
if (isStatic && strcmp(signature, "sleep(_)") == 0) return C_sleep;
}
}
return NULL;
}
 
static void writeFn(WrenVM* vm, const char* text) {
printf("%s", text);
fflush(stdout); // as we're redirecting stdout to a file
}
 
void errorFn(WrenVM* vm, WrenErrorType errorType, const char* module, const int line, const char* msg) {
switch (errorType) {
case WREN_ERROR_COMPILE:
printf("[%s line %d] [Error] %s\n", module, line, msg);
break;
case WREN_ERROR_STACK_TRACE:
printf("[%s line %d] in %s\n", module, line, msg);
break;
case WREN_ERROR_RUNTIME:
printf("[Runtime Error] %s\n", msg);
break;
}
}
 
char *readFile(const char *fileName) {
FILE *f = fopen(fileName, "r");
fseek(f, 0, SEEK_END);
long fsize = ftell(f);
rewind(f);
char *script = malloc(fsize + 1);
size_t ret = fread(script, 1, fsize, f);
if (ret != fsize) printf("Error reading %s\n", fileName);
fclose(f);
script[fsize] = 0;
return script;
}
 
static void loadModuleComplete(WrenVM* vm, const char* module, WrenLoadModuleResult result) {
if( result.source) free((void*)result.source);
}
 
WrenLoadModuleResult loadModule(WrenVM* vm, const char* name) {
WrenLoadModuleResult result = {0};
if (strcmp(name, "random") != 0 && strcmp(name, "meta") != 0) {
result.onComplete = loadModuleComplete;
char fullName[strlen(name) + 6];
strcpy(fullName, name);
strcat(fullName, ".wren");
result.source = readFile(fullName);
}
return result;
}
 
int main(int argc, char **argv) {
fileName = argv[1];
WrenConfiguration config;
wrenInitConfiguration(&config);
config.writeFn = &writeFn;
config.errorFn = &errorFn;
config.bindForeignMethodFn = &bindForeignMethod;
config.loadModuleFn = &loadModule;
WrenVM* vm = wrenNewVM(&config);
const char* module = "main";
const char* fileName = "Run_as_a_daemon_or_service.wren";
char *script = readFile(fileName);
WrenInterpretResult result = wrenInterpret(vm, module, script);
switch (result) {
case WREN_RESULT_COMPILE_ERROR:
printf("Compile Error!\n");
break;
case WREN_RESULT_RUNTIME_ERROR:
printf("Runtime Error!\n");
break;
case WREN_RESULT_SUCCESS:
break;
}
wrenFreeVM(vm);
free(script);
return 0;
}</syntaxhighlight>
 
{{out}}
Sample output:
<pre>
$ ./dumper dump
$ tail -f dump
Sat Feb 03 20:02:20 2024
Sat Feb 03 20:02:21 2024
Sat Feb 03 20:02:22 2024
Sat Feb 03 20:02:23 2024
Sat Feb 03 20:02:24 2024
Sat Feb 03 20:02:25 2024
Sat Feb 03 20:02:26 2024
Sat Feb 03 20:02:27 2024
Sat Feb 03 20:02:28 2024
Sat Feb 03 20:02:29 2024
^C
$ pkill -x dumper
$ rm dump
</pre>
 
{{omit from|Brlcad}}
9,482

edits