# rc.d script - autobooted or invoked interactively?



## Basil Hendroff (Jul 27, 2020)

Hello! First time poster. I'm new to rc.d scripting and have been studying the various resources and tinkering for several months now, but I'm not confident enough to answer the following question:

Is it possible for an rc.d initialisation script to determine whether it has been autobooted (such as when a jail starts) or invoked interactively (such as when `service xyz start` is issued from the command line)? If it is possible, can I please get some expert advice on what I should be looking for?


----------



## SirDice (Jul 27, 2020)

Basil Hendroff said:


> Is it possible for an rc.d initialisation script to determine whether it has been autobooted (such as when a jail starts) or invoked interactively (such as when  service xyz start is issued from the command line)?


That's essentially the same thing. There is no difference in the way these scripts are called or executed. They'll do the exact same thing in both cases.


----------



## Mjölnir (Jul 27, 2020)

RTFM sh(1) tells about special variables: _$PPID:  The parent process ID of the invoked shell.  This is set at startup unless this variable is in the environment.  A later change of parent process ID is not reflected.  A subshell retains the same value of PPID._

Hairy: It should be possible to use that to find the invoking process name and combine with the output of `ps -xd`.
Easy: UTSL /etc/rc contains a variable _autoboot_, at a quick glance it does not get exported.  So the easiest solution might be to patch /etc/rc to export that variable.


----------



## Basil Hendroff (Jul 27, 2020)

Some context may be helpful. I've raised an issue described in this Caddy forum thread How to use the expanded form of php_fastcgi?

To summarise, the issue has nothing to do with php_fastcgi. Caddy fails initially if started from a jail. The problem is that there is no place for log output to go. The issue can be circumvented by having the initialisation script redirect `stdout`and `stderr` to a file. However, that should not be a blanket requirement. If commands are invoked interactively, it's desirable to have output redirected to the terminal. So, unless I'm thinking about this the wrong way, the logic I'm grappling with is 'If autostarted, redirect output to a file, otherwise, redirect output to the terminal'.

I'd like to go back to the port maintainer at Bug 246623 - [NEW PORT] www/caddy2 (Update to www/caddy) with an approach, if one is available, as suggested by the brains trust.


----------



## Basil Hendroff (Jul 27, 2020)

mjollnir said:


> Easy: UTSL /etc/rc contains a variable _autoboot_, at a quick glance it does not get exported. So the easiest solution might be to patch /etc/rc to export that variable.


I did see a reference to the variable _autoboot _in rc(8), but I'm still unclear on how to use it. I'm unfamiliar with the term 'export'. Can you please elaborate?


----------



## PMc (Jul 27, 2020)

Basil Hendroff said:


> Is it possible for an rc.d initialisation script to determine whether it has been autobooted (such as when a jail starts) or invoked interactively (such as when `service xyz start` is issued from the command line)? If it is possible, can I please get some expert advice on what I should be looking for?



The radical answer is: if the script could detect this, it should be considered a flaw in the rc.d software.

Now let me explain this: when you develop an application (or port it to some system), you will test it by starting it in your terminal. Then, if all is well, you copy your start command into an rc.d script and expect the application to come up at reboot. And, in most cases, it will NOT do so.

The cause of this is, there are dozens of things that are different at system bringup than in a terminal: there is no terminal, no job control, no stdio, and lots of other things which are usually taken for granted by the interactive user. And in consequence, the application will either not start or behave differently.

So then you will have to start searching for the problem, which is not always easy. Therefore, the rc.d system should start an application always in the same way, no matter if invoked interactively or at system start. (We do rarely boot our systems, and we do not like bad surprises after a reboot.)
This is not possible in fullness, because there may be interdependencies - i.e. the sequence in which the applications are started one after another may matter. And there are certainly some tricks by which an experienced programmer could figure out what is the case, anyway.



Basil Hendroff said:


> Caddy fails initially if started from a jail. The problem is that there is no place for log output to go. The issue can be circumvented by having the initialisation script redirect `stdout`and `stderr` to a file.



This is a very typical example of these issues that appear when integrating an application. Ideally these should be pointed to /dev/null, or the application run under daemon(8) and the output written to syslogd(8).



> However, that should not be a blanket requirement. If commands are invoked interactively, it's desirable to have output redirected to the terminal. So, unless I'm thinking about this the wrong way, the logic I'm grappling with is 'If autostarted, redirect output to a file, otherwise, redirect output to the terminal'.



I understand. But I think this should be done differently. The rc.d scripts are intended for starting applications that will continue to run - as long as the server runs or until they are stopped again. If you re-route stdio to your terminal, and later log out, nobody will stop that application, and you will be back at the starting point where the application doesnt have a stdio. Or, worse, the next person logging in on your terminal will receive the output from your application (this was very common on the old time-sharing machines with hard-wired serial terminals - it is no longer the case with current virtual terminals).

So I don't think this is a good idea. What You might do instead is create a debug mode: make another script to start the application from within your terminal, in a temporary way only for as long as you work on it. And there you can handle things differently.

Some other points from your linked site:


> how important is it that Caddy V2 create a PID file,



You want that PID file so that you can clearly identify your application when you want to stop it again. If the application produces a pid file, then rc.d can use that to stop it. If it doesn't, rc.d must resort to grepping around in the ps(1) output, and that can be erroneous.



> or require LOGIN and DAEMON?



If you run the application with stdout routed to syslogd (as recommended above), then it should be started only after syslogd has started. There may be other things, depending on what system ressources the application may want to use.


----------



## Mjölnir (Jul 27, 2020)

Basil Hendroff said:


> The problem is that there is no place for log output to go. [...]


You can use rc.subr(8)'s _err(), warn(), info() & debug()_?


----------



## Basil Hendroff (Jul 27, 2020)

PMc said:


> Ideally these should be pointed to /dev/null, or the application run under daemon(8) and the output written to syslogd(8).


This seems counterintuitive to me. I can understand this if the output is not useful, but if it is potentially useful, would it not be simpler to direct the output to a file than to deal with daemon and syslogd?

Btw, thank you for the perspective you have provided. It's been very informative.


----------



## PMc (Jul 28, 2020)

Basil Hendroff said:


> This seems counterintuitive to me. I can understand this if the output is not useful, but if it is potentially useful, would it not be simpler to direct the output to a file than to deal with daemon and syslogd?



That depends on how complex the installation is and how many subsystems are running. Daemon does a few more things: it provides a pidfile if the application doesn't, or it can restart the application when it tends to crash (hmja, it also has some flaws). 
If you direct output to a file, you cannot have multiple applications write into the same file (that will mangle the output), so you need a separate file for each. You need to make up a place for these files, manage the diskspace, and provide for a means to rotate them when they grow big - and properly signal the application that it closes and reopens stdout, otherwise that will not work so well (if it can do that at all). ah, and beware the file permissions: are there sensitive data in the logs?
With syslog you can regroup the messages by importance (and it reads a lot easier when e.g. the webserver, appserver and dbserver write their important stuff into the same file and you can rightaway in-sequence read what has happened), you can route the routine stuff (e.g. webserver access logs) to separate files for automated processing, can route certain things to a different machine (for security or ease of administration), and you have newsyslog(8) to properly rotate the logs, maintain filespace and signal the daemon.

If you have five or ten logfiles, this is not really an issue. But if you have 50 or 100, it may look different. And it is easy to get to that - a multihomed webserver will create lots, a nameserver, mailserver, some database engines, not to mention the security and housekeeping stuff.
You will usually not go thru the effort of configuring these things until it starts to hurt otherwise.


----------



## mark_j (Jul 28, 2020)

Basil Hendroff said:


> Some context may be helpful. I've raised an issue described in this Caddy forum thread How to use the expanded form of php_fastcgi?
> 
> To summarise, the issue has nothing to do with php_fastcgi. Caddy fails initially if started from a jail. The problem is that there is no place for log output to go. The issue can be circumvented by having the initialisation script redirect `stdout`and `stderr` to a file. However, that should not be a blanket requirement. If commands are invoked interactively, it's desirable to have output redirected to the terminal. So, unless I'm thinking about this the wrong way, the logic I'm grappling with is 'If autostarted, redirect output to a file, otherwise, redirect output to the terminal'.
> 
> I'd like to go back to the port maintainer at Bug 246623 - [NEW PORT] www/caddy2 (Update to www/caddy) with an approach, if one is available, as suggested by the brains trust.


Maybe test for $TERM in the rc script? You could test STDIN: 

```
if [ -t 0 ]; then
# interactive
else
#not interactive
fi
```

Or abandon the use of rc.d and use rc.local instead?


----------



## Basil Hendroff (Jul 28, 2020)

Thank you to all of you who have taken the time to respond to my first post on this forum. The feedback has been tremendous. I have appreciated each and every one of your responses.


----------



## Mjölnir (Jul 28, 2020)

Basil Hendroff said:


> I did see a reference to the variable _autoboot _in rc(8), but I'm still unclear on how to use it. I'm unfamiliar with the term 'export'. Can you please elaborate?


A sh(1)ell variable (e.g. in a script) can be _exported_ into the environ(7)ment to be available for consecutive shells or scripts.  This is one of the shell's methods to pass on values.  The other notion is by positional parameters. E.g. `export my_var=auto && ./script.sh` then _my_var_ is visible in the script.


----------

