Log4j: Setting the generated log filename to include hostname - java-8

I am trying to generate logs using log4j. Logging part is working correctly, but I want to include the hostname (where the logs are generated) to be appended in the filename.
for eg: my current logfile name: logger.2019-06-12-06-14
what i want: logger_$HOST.2019-06-12-06-14
, where $HOST is the hostname
I have already seen other posts in stackoverflow and depending on that I have set the hostname in my Java code where I think its getting set before calling log4j
static {
try {
HOST_NAME = InetAddress.getLocalHost().getCanonicalHostName();
} catch (UnknownHostException e) {
HOST_NAME = "localhost";
}
System.setProperty("hostname", HOST_NAME);
}
and have modified the cfg file (where we have properties defined for all the loggers), to include the system property:
*.*.log4j.appender.MyLogger.File=/logs/logger_$hostname;
But the resultant filename generated is logger_$hostname.2019-06-12-06-14 (which is literally $hostname instead of the property value)
In the posts, it does mention that the way to assign the variable in the cfg file is logger_${hostname} but while compiling it throws err with unexpected {, so I just put $hostname instead.
I have tried other ways too, like putting
*.*.log4j.appender.MyLogger.File=/logs/logger_$env:hostname;
*.*.log4j.appender.MyLogger.File=$hostname;
*.*.log4j.appender.MyLogger.File=/logs/logger_$HOST;
(thinking since its running in unix, it might pick the HOST variable :( )
but no luck so far. Any ideas what I might be doing wrong?
BTW, I am calling the logger by this:
private static Logger logger = Logger.getLogger("MyLogger");
So, is it possible to set the hostname from the class where I am logging. I do want to rotate my logs every minute, so dont want to mess with other log4j settings. My complete log4j appender properties:
*.*.log4j.logger.myLogger=(INFO,MyLogger);
*.*.log4j.additivity.myLogger=false; # this logger does not show up in main logs
*.*.log4j.appender.MyLogger.File=/logs/logger_$hostname;
*.*.log4j.appender.MyLogger.layout=org.apache.log4j.PatternLayout;
# %n: new line for each entry
*.*.log4j.appender.MyLogger.layout.ConversionPattern="%m%n";
*.*.log4j.appender.MyLogger.Append=true;
*.*.log4j.appender.MyLogger.ImmediateFlush=true;
*.*.log4j.appender.MyLogger.Encoding=UTF8;
# Enable 1 minute rotation
*.*.log4j.appender.MyLogger.DatePattern="'.'yyyy-MM-dd-HH-mm";
# Disable periodic flush since files will be flushed upon rotation that happens every minute
*.*.log4j.appender.MyLogger.PeriodicFlush=false;
Any ideas to fix it will be very helpful. (And apologies since its kind of a repetitive question but I am not able to figure out the issue with the earlier posts :( )

You can use the ${env:HOST} option in the log4j2.xml for environment lookup as mentioned in the documentation: https://logging.apache.org/log4j/2.0/manual/lookups.html#EnvironmentLookup
For example:
<RollingRandomAccessFile name="CustomLoggerRandomFile"
fileName="logs/${env:HOST}_system.log"
filePattern="${env:HOST}_system-%d{yyyy-MM-dd}-%i.log.gz"
immediateFlush="false">
EDIT: I assumed that you are using log4j2 and the $HOST variable must be created in the host machine (where the logs are generated) as an environment variable.

I have replaced ${hostname} by ${hostName} and it worked.
<RollingFile name="LogToFile" fileName="${env:LOG_ROOT}/${env:LOG_RELEASE}/myFile.${hostName}.json" in log4j2.xml

Related

How do nested variables within the .env file work in CodeIgniter 4

Under the "Nesting Variables" section in Codeigniter4 site:
"To save on typing, you can reuse variables that you’ve already specified in the file by wrapping the variable name within ${...}"
link to CI nesting Variables section
example in the documentation:
BASE_DIR="/var/webroot/project-root"
CACHE_DIR="${BASE_DIR}/cache"
TMP_DIR="${BASE_DIR}/tmp"
I was trying to use the following
app.baseURL = 'http://localhost:8080/'
google.redirect = ${app.baseURL}Google
However, it's assigning it as a literal when print_r($_ENV)
[google.redirect] => ${app.baseURL}Google
I've tried using non-namespaced keys including BASE_DIR (per the example) and it keeps printing as a literal.
What's strange - When I use the following:
CI_ENVIRONMENT = development
google.redirect = ${CI_ENVIRONMENT}Google
The result when print_r is:
[CI_ENVIRONMENT] => development
[google.redirect] => developmentGoogle
My question is - What am I doing incorrectly and/or how should these be set/used correctly?
According to the documentation, I should be able to use any key within the .env file that was already assigned using
${somekeyinthisfile}
After a bit of looking, there is a more recent file up at
https://github.com/codeigniter4/CodeIgniter4/blob/develop/system/Config/DotEnv.php
with all the "other" changes...
This was a Bug Fix. So get that file and you will be good to go.
I am pretty sure that the intention wasn't to allow app.xxx settings to be used as variables as the documentation clearly shows, by not
showing them being used. ( yes its 6am now ...)
BUT it is your code to do with as you please...So if you want to use app.xxx as variables...
The Only Thing missing is the DOT (.) in the regex
If you look on Line 272 - system/Config/DotEnv.php inside method resolveNestedVariables() and add a . (dot) into the regex, that will make all your app.things work.
$value = preg_replace_callback(
'/\${([a-zA-Z0-9_.]+)}/',
function ($matchedPatterns) use ($loader) {
I have added a dot (.) at the end of the [a-zA-Z0-9_
So
'/\${([a-zA-Z0-9_]+)}/',
becomes
'/\${([a-zA-Z0-9_.]+)}/',

Read environment variables in revel app.conf

Revel uses app.conf for storing configuration. I want my configuration to get value from environment variable using os.Getenv(key)
How can I do it? Should I use revel.Config to make changes? if so where do I place it?
Or is there another way?
I use it mainly for storing database information (I don't want to enter my credential in configuration files)
Thank you
Revel uses revel/config for managing app.conf.
And the only place revel/config foes read from the environment variable is in type.go (c *Config) String() method.
// $ environment variables
computedVal, _ = c.computeVar(&value, envVarRegExp, 2, 1, func(varName *string) string {
return os.Getenv(*varName)
})
That means you could add in a config file values based on the name of environment variable, which would allow you to use said environment variable to modify the config.
See an example in the revel/config REAMD.md file.
[DEFAULT]
host: www.example.com
protocol: http://
base-url: %(protocol)s%(host)s <====
The OP pveyes points out to this comment in type.go:
// substitute by new value and take off leading '%(' and trailing ')s'
// %(foo)s => headsz=2, tailsz=2
// ${foo} => headsz=2, tailsz=1
So:
when using environment variables use ${ENV_VARS}, and
for unfolding variables use %(UNF_VARS)s

startup script in freebsd is not running

I have been trying to run a shell script at boot time of freebsd. I have read all simmilar questions in stackoverflow and tried. But nothing is worked. This is the sample code that i tried is dummy.
#!/bin/sh
. /etc/rc.subr
name="dummy"
start_cmd="${name}_start"
stop_cmd=":"
dummy_start()
{
echo "Nothing started."
}
load_rc_config $name
run_rc_command "$1"
Saved with name of dummy.
Permissions are -r-xr-xr-x.
in rc.conf file made dummy_enable="YES".
The problem is, when i rebooted my system to test, dummy file is not there. So script is not executing. what else need to do run my dummy script.
SRC:http://www.freebsd.org/doc/en/articles/rc-scripting/article.html#rc-flags
You need to add rcvar="dummy_enable" to your script. At least for FreeBSD 9.1.
Call your script with parameter rcvar to get the enabled status:
# /etc/rc.d/dummy rcvar
# dummy
#
dummy_enable="YES"
# (default: "")
And finally start it with parameter start - this won't start the service/script unless dummy_enable is set in /etc/rc.conf (or /etc/rc.conf.local, or /etc/defaults/rc.conf)
# /etc/rc.d/dummy start
Nothing started.
One possible explanation is that rcorder(8) says:
Within each file, a block containing a series of "REQUIRE", "PROVIDE",
"BEFORE" and "KEYWORD" lines must appear.
Though elsewhere I recall that if a file doesn't have "REQUIRE", "PROVIDE" or "BEFORE", then it will be arbitrarily placed in the dependency ordering. And, it could be that the arbitrary placement differs between the first run up to $early_late_divider and in the second run of those after $early_late_divider.
OTOH, is this a stock FreeBSD, or some variant? I recall reading that FreeNAS saves its configuration somewhere else and recreates its system files on every boot. And, quite possibly that /etc is actually on a ramdisk.
Also, /usr/local/etc/rc.d doesn't come into existence until the first port installing an rc file is installed.

where can I see the print string when i add the code "System.out.println("test string");" in NameNode.java file?

Under NameNode.java file
Try to added test code of print string in main() function, the code as below:
System.out.println("test string");
where can I see the print string?
*code compiler successful and used new generation file(hadoop-core-1.0.4.jar) replace to each node.
*All daemon has restart. but not found the print string on terminal.
If you've restarted your name node service, these sys outs will probably go the the name node log file (which can be in a variety of locations depending on your hadoop disto / install). The hadoop-daemon.sh file defines the file as follows:
$HADOOP_LOG_DIR/hadoop-$HADOOP_IDENT_STRING-$command-$HOSTNAME.out
So you'll find it in the HADOOP_LOG_DIR, under the name hadoop-$HADOOP_IDENT_STRING-nanmenode-$HOSTNAME.out - where the other variables will be replaced depending on the runtime user and hostname of your namenode service.
I would suggest you use the predefined logger, rather then System.err / System.out:
LOG.info("log message");

How can I log to a specific file in linux using logger command?

I will run the following script:
#!/bin/bash
./myprogram
#get exit code
exitvalue=$?
#log exit code value to /var/log/messages
logger -s "exit code of my program is " $exitvalue
But I don't want log message to be written in /var/log/messages because I don't have root privileges. Instead I want it to be written to a file in my home directory: /home/myuser/mylog
How should I modify logger command above?
I don't think you really need to (or want to) involve logger/syslog for this. Simply replace the last line of the script with:
echo "Exit code of my program is $exitvalue" >> /some/file/that/you/can/write/to
The short "official" answer is that, unfortunately, you can't.
However, in most cases (e.g. on many Linux distros) you may just be lucky enough to have a logger implementation that both supports the --no-act option, and also implements some message formatting on its own (see below), in which case you can use a (moderately ugly) command like this to put a) a properly formatted message, b) to a file, c) not polluting the system logs:
logger --no-act -s "Oh dear..." 2>&1 | sed 's/^<[0-9]\+>//' >> /tmp/my.log
(Shout out to #BasileStarynkevitch, and #Kieveli, who both mentioned parts of it before, just not the whole story.)
Notes:
1) To match the usual log file format, I had to "sed off" the <PRIVAL> field (PRIVAL = FACILITY * 8 + PRIORITY) that got prepended to the output on my Debian boxes. Your mileage may vary.
2) POSIX itself does not define how exactly the logger command should treat (any of) its options. E.g. the GNU logger does not support --no-act at all.
Also, when posting the original version of this answer 2 years ago, -s on my system did not do any formatting to the printed output, it just echoed the raw message alone, rendering it completely useless. (I didn't use Systemd at that time, which might explain the difference, seeing various conditional Systemd-related calls in the logger source code, but this is just vague guesswork.)
3) The most likely reason why the logger command has been so "historically unfriendly" for this trivial use case is that it's just a fairly simple frontend to the system logger. This means that anything you feed to it basically goes right through to syslogd (or systemd-journald etc.), which, in turn, does all sorts of other further processing, and dispatching (to various outlets: files, sockets etc., both local and remote), as well as bridging permission levels (so in your example you could still log to syslog or user.log, for instance, even though you may have no permission to write to those files directly).
For logger to be able to properly log to a file directly, it would either have to (re)implement some of the duties of the system logger, and the syslog() std. library function, or it would be not much more capable than a trivial echo one-liner (less complex, perhaps, even than the above logger invocation! ;) ). Either way, that seems like a bad idea.
A better solution could be if the POSIX interface (logger, syslog()) had a way to specify an ad-hoc outlet/facility parameter (like a filename) along with the message, so one could log to custom files without reconfiguring the system (which normal users have no permission to do anyway).
However, for the lack of anything better, the "canonical" Linux logger implementation actually does seem to duplicate some of the syslog functionality, so most of us can just enjoy that luxury for free. ;)
If you want to use logger so that the message appears both in the system logs and in some file of yours, you might do
logger -s your message 2> $HOME/somefile
since the -s option to logger also outputs on stderr which is redirected to the file with 2>
You could want to use 2>> $HOME/somefile to append (not overwrite) your $HOME/somefile (read about bash redirections), and (see logger(1) for details) you may prefer to pass the program option --id=$$ to logger.
I think your better choice would be to use the date command rather then logger in cases where you don't want to write to the syslog files (and don't have privs to do so).
See "timestamp before an echo" for details on how to use date to prefix a message with a date and write it to a file.
You create a bash function that looks like the following, adjusting the date format string to get what you want:
echo_time() {
echo `date +'%b %e %R '` "$#"
}
In your bash script, you would then use:
echo_time "Your message here" >> ${LOGFILE}
Which would put the following in your ${LOGFILE} file:
Mar 11 08:40 your message here
$ man logger
Logger provides a shell command interface to the syslog(3) system log module.
You'll need to change your syslog configuration if you want it to log things to other places. You could establish a certain facility that has an output file in your home directory, for example. You would need to be root to do that, though.
You can create a small logger function like this on top of your script file:
#! /bin/bash
#LOG FILE location
log_file=/tmp/mylogfile.log
#the LOG function
LOG()
{
time=$(date '+%Y-%m-%d %H:%M:%S')
echo "$time"" >>> "$1 >>${log_file}
}
message= echo "test logger message"
#to send loggers to your log file use
LOG "my message logged to my log file with timestamp = ""$message"
check output :
head -1 /tmp/mylogfile.log
2019-09-16 14:17:46 >>> my message logged to my log file with timestamp = test logger message
I you can use cat - witch echoes your output then >> [file] witch prints the output to [file] inset of terminal so the command would be
cat - >> [file]
the down side is you have to use ctrl+C or ctrl+Z to exit logger is better for online code

Resources