Replies: 2 comments
-
It sounds like this describes an operating system service. Depending on your server operating system there are tools you can use to setup Deno to always run on the server. |
Beta Was this translation helpful? Give feedback.
-
@goodwin74 This guide is only for Windows though. SetupThe following example is from https://github.com/oakserver/oak import { Application } from "https://deno.land/x/oak/mod.ts";
const app = new Application();
app.use((ctx) => {
ctx.response.body = "Hello World!";
});
await app.listen({ port: 8000 }); Give it a name like Once you've got your ContextOn Windows, an executable has a SUBSYSTEM field (https://wiki.osdev.org/PE). The Script and Auto-Running (and how to edit exe details)Below (or attached) I've thrown together a medium-size script to change the subsystem to WINDOWS. This means when you launch the program and it'll start and run in the background. If you want it to run on Windows startup you can right-click It'll show up as The CodeAll in all, it's a bit hacky, but hopefully it gets the job done 🙂. Show the 'change_exe_subsystem.ts' code (tested in Deno 1.13.2)...// --allow-read --allow-write change_exe_subsystem.ts
async function readN(r: Deno.Reader, n: number): Promise<Uint8Array | null> {
const buf = new Uint8Array(n);
let nRead = 0;
// a null value of r.read() will nullish coalesce into NaN and
// polute nRead, causing (nRead < n) to be false and the loop to exit
while (nRead < n) {
nRead += await r.read(buf.subarray(nRead)) ?? NaN;
}
return isNaN(nRead) ? null : buf;
}
async function writeAll(w: Deno.Writer, buf: ArrayBufferView): Promise<void> {
const bytes = new Uint8Array(buf.buffer, buf.byteOffset, buf.byteLength);
let nWritten = 0;
while (nWritten < bytes.byteLength) {
nWritten += await w.write(bytes.subarray(nWritten));
}
}
function view(buf: ArrayBufferView) {
return new DataView(buf.buffer, buf.byteOffset, buf.byteLength);
}
// replace 'my_oak_server.exe' with your server binary
const PATH_TO_BINARY = "./my_oak_server.exe";
const bin = await Deno.open(PATH_TO_BINARY, { read: true, write: true });
// we're going to validate (loosely) that its a valid EXE/MZ
// reset to index 0, just to be sure
await bin.seek(0, Deno.SeekMode.Start);
const magicBytes = await readN(bin, 2);
if (magicBytes == null) {
console.log("Encountered EOF at magicBytes");
Deno.exit(1);
}
const binMagic = new TextDecoder().decode(magicBytes);
if ("MZ" != binMagic) {
console.log(`☹ we didnt find a valid exe at ${PATH_TO_BINARY}`);
Deno.exit(1);
}
// we now know we have a valid exe file
// next we need to get the offset of the 'PE Header'
const PE_ADDRESS_OFFSET = 0x3C;
await bin.seek(PE_ADDRESS_OFFSET, Deno.SeekMode.Start);
// read the peHeaderPointer as 32bit little-endian int/dword/u32
const peHeaderPointerBytes = await readN(bin, 4);
if (peHeaderPointerBytes == null) {
console.log("Encountered EOF at peHeaderPointerBytes");
Deno.exit(1);
}
const peHeaderPointer = view(peHeaderPointerBytes).getUint32(0, true);
// we've got the offset of the PE header now
// we'll go to that offset, then a further 92 bytes
// this is where the subsytem field is
await bin.seek(peHeaderPointer + 92, Deno.SeekMode.Start);
// WINDOWS subsystem (don't show a terminal)
// CONSOLE subsystem (show a terminal when running)
const SUBSYSTEM_WINDOWS = 2;
const SUBSYSTEM_CONSOLE = 3;
// before we modify the value we'll do a very rough check
// to make sure that we are modifying the right field
// we'll need to get it as a little-endian u16
const subsystemBytes = await readN(bin, 2);
if (subsystemBytes == null) {
console.log("Encountered EOF at subsystemBytes");
Deno.exit(1);
}
const subsystem = view(subsystemBytes).getUint16(0, true);
if (!(SUBSYSTEM_WINDOWS == subsystem || SUBSYSTEM_CONSOLE == subsystem)) {
console.log("Oops! The subsystem is not WINDOWS=2 or CONSOLE=3.");
console.log("We might be editing the wrong field,");
console.log(" _or_ the EXE uses a different subsystem.");
Deno.exit(1);
}
// okay, now we are pretty sure about the file
// let's update its subsystem
const newSubsystemData = new Uint16Array(1);
view(newSubsystemData).setUint16(0, SUBSYSTEM_WINDOWS, true);
// go back to the subsytem field
await bin.seek(peHeaderPointer + 92, Deno.SeekMode.Start);
// write out our data.
await writeAll(bin, newSubsystemData);
// finish up with a helpful message
const newSubsystemValue = view(newSubsystemData).getUint16(0, true);
if (SUBSYSTEM_WINDOWS == newSubsystemValue) {
console.log(`Done! Changed ${PATH_TO_BINARY} subsystem=2, WINDOWS.`);
}
else if (SUBSYSTEM_CONSOLE == newSubsystemValue) {
console.log(`Done! Changed ${PATH_TO_BINARY} subsystem=3, CONSOLE.`);
} |
Beta Was this translation helpful? Give feedback.
-
Now if you exit the terminal, the oak server crashes. And the script is not available at the URL.
How to run Deno in the background so that it always runs on the server until it is explicitly stopped by a command in the terminal?
Beta Was this translation helpful? Give feedback.
All reactions