Puppet "onlyif" attribute cannot find not(!) operator - node.js

I am trying to figure out if Node package PM2 is installed in the path and executable or not with the following puppet code.
exec { "create symbolic link for pm2":
cwd => "${pm2_link_dir}",
path => ['/usr/bin','/bin','/usr/sbin','/sbin'],
onlyif => "! which node &> /dev/null",
command => "ln -s ../lib/node_modules/pm2/bin/pm2 pm2"
}
It is telling me cannot find command "!". Is this the right way to find out if some program is installed and executable?? And why puppet cannot understand The not operator?? I am working on Redhat master and slave.

And why puppet cannot understand The not operator?
The ! operator is provided by the shell; it is not a command. You are using Exec's default provider (posix) which runs your commands directly rather than via a shell. (Or so it is documented to do. It has recently come to light that sometimes the posix provider runs commands via the shell, in apparent contradiction of its docs.)
It is anyway a bit silly to use ! in an Exec's onlyif attribute, when you could instead drop the ! and switch to an unless attribute instead. And drop the redirection, which also relies on the shell.
Is this the right way to find out if some program is installed and executable?
It is usually better to know whether the program should be available on the specific target node, and where necessary to ensure that it is available. If you must inquire about node state, then it is usually better to do that via a custom fact.
With that said, I don't think your approach is inherently wrong, though of course it will only look for the requested program in the path you specify in the Exec.

Related

Command not found in WSL2 even though it's on the path

I'm having an issue with WSL2:
$ where b4a
/usr/local/bin/b4a
$ b4a new
/usr/local/bin/b4a: 1: Not: not found
Even though where finds commands, I can't run them. And it's not a PATH issue either:
echo $PATH
/usr/local/sbin:/usr/local/bin:[...]
And b4a isn't the only command with this problem. What could be the cause? My distribution is Debian 10 and host is Windows 10.
Not necessarily a full answer, but hopefully the troubleshooting methods you need to arrive at a solution ...
Note that it doesn't say that the command itself isn't found. For instance, if you run:
# lllllllllll
lllllllllll: command not found
That's truly a command not found. This is different. While I don't (yet) know the exact cause, this seems closer to the issues we might see with improperly quoted paths with spaces in a shell script.
You mention that other commands have this problem -- Is there something in common with the commands that don't work properly? Is it possible that they are all shell scripts?
Try several things to debug:
Start WSL without your startup profile. It's very likely that something (or you) added a line that is causing problems. From PowerShell or CMD:
wsl ~ -e bash --noprofile --norc
b4a
If that works, then there's a problem in one of your startup files that you'll need to debug. Look for anything modifying environment variables without proper quoting, especially the PATH. WSL automatically appends the Windows path to your Linux path to make it easy to run Windows commands, but the fact that almost every Windows path has spaces in it can cause problems for unsuspecting scripters that don't take this corner case into account.
Having a space in a path is fully allowed in Linux, but some scripts just don't handle it properly.
If the command that is failing is a shell script, trying starting it with:
bash -x /usr/local/bin/b4a
Or even start WSL with wsl ~ -e bash -x to see all trace output from the shell.
In this case, you'll be looking for some problem in the script right around where it actually fails.
If all else fails, you can disable WSL's PATH modification via its config file:
sudo -e /etc/wsl.conf
Add the following:
[interop]
appendWindowsPath = false
Then exit Debian, run wsl --shutdown and restart Debian. Try the b4a command again.
If this works, then the problem is almost certainly due to some problem in the PATH quoting in these commands. I don't recommend it as a permanent solution since you will have to type out the full path of Windows applications each time you want to run them.

How do I use puppet to execute a script on a linux VM

I need puppet to execute a script that is inside an installed app. In addition I need to run only if it detects an older version of the and is not on a certain server and then install the new version
I have tried a bunch of stuff and I am losing track. First I tried to use a cd to go to the where the script and then tried running the script directly but I keep getting the same error.
install.pp
# Install required packages
class tripwire::install {
exec { 'uninstall_tripwire':
command => './usr/local/tripwire/te/agent/bin/uninstall.sh',
cwd => '/usr/local/tripwire/te/agent/bin',
path => '/usr/bin/sh',
onlyif => [
"${::fqdn} != 'server.com'",
'/usr/bin/test -f
/usr/local/tripwire/te/agent/bin/uninstall.sh',
"grep -c '8.6.0' /usr/local/tripwire/te/agent/data/version",
],
notify => Exec['install_tripwire'],
I would think this would it would execute the script but all I get is:
Error: /Stage[main]/Tripwire::Install/Exec[uninstall_tripwire]: Could not evaluate: Could not find command 'server.com'
I need puppet to execute a script that is inside an installed app. In
addition I need to run only if it detects an older version of the and
is not on a certain server and then install the new version
The particular task you seem to be trying to perform with your Exec duplicates standard behavior of the Package resource. You really, really ought to manage software via packages, even if you have to do some packaging yourself and maintain a local package repository. The time spent on packaging is easily offset by the time saved managing software, even with Puppet in the mix.
Additionally, as far as controlling which machines to operate upon goes, you ought to be treating that as a matter of classification. If that class should not be applied to machine server.com then it should not be declared into that machine's catalog. If it should be applied differently to that machine than to others, then it should be appropriately parameterized, and those parameters used (at classification time, maybe with the help of Hiera) to select the appropriate behavior for each target machine.
Nevertheless, with respect to the code actually presented, the error message
Could not evaluate: Could not find command 'server.com'
reflects that this element of your onlyif array ...
"${::fqdn} != 'server.com'",
... is not a command. onlyif requires a command or an array of them that can be executed on the target system, so maybe this, instead:
"test ${::fqdn} != server.com",
Additionally, this looks wrong:
command => './usr/local/tripwire/te/agent/bin/uninstall.sh',
Remove the leading ., unless you really intend to resolve that path against the working directory. And if you do intend to resolve it as a relative path then I urge you to instead expand it to an absolute one.
Furthermore, this probably doesn't do what you intend:
path => '/usr/bin/sh',
The path attribute names a binary search path, like the PATH environment variable. You may indeed want to specify one, such as maybe '/bin:/usr/bin:/sbin:/usr/sbin', but if the intention of what you did put was for the commmand to be executed via a shell, then you were looking for
provider => 'shell',

How to run a shell command after saving file in Sublime 3

I've been trying to create a custom shell command to run after saving the file im working on. The command should run in the same location of the file.
I've came up with this, under user-preferences, but with no success.:
"on_post_save_user": [
{
"cmd": ["shell command"]
}
.
Based on your question, I'm going to assume that you're using the Hooks package to be able to run arbitrary commands based on events. If you haven't installed that package yet, then you'll need to do that too; the items talked about here are not available in core Sublime.
This package can execute any arbitrary command that you want, but note that this means Sublime commands; that is commands provided either by the core of Sublime or by packages and plugins that you have installed. Thus including the name of a shell command will not work; Sublime silently ignores commands that you tell it to run that it doesn't know about.
That said, the exec command is available directly in any Sublime installation and can execute any arbitrary shell command or program that you tell it to. This command is what is used to execute a build system, for example.
In fact, most of the keys available in a Build system by default (excluding the keys that tell Sublime when your build should apply) are actually arguments to the exec command that tell it what to execute.
Of particular interest to you is the shell_cmd argument, which takes any arbitrary command that you might enter in a command prompt and executes it.
Based on the documentation of the package in question, the configuration option you want would be something like this:
"on_post_save_user": [
{
// Runs `exec` command
"command": "exec",
// Invokes `exec` with `shell_cmd="google-chrome"`
"args": {
"shell_cmd": "google-chrome"
},
// Runs `exec` via `window.run_command`
"scope": "window"
}
]
With the caveat that I don't use this particular package and I can't verify that this is all that might be required, this tells the package to run the exec command (which is indeed a window command), telling it to execute google-chrome.
Other options may be required to exec to do what you want, depending on what that is. It's also unclear from the package documentation whether it supports the standard build system variables like $file to represent the current file or not, which may or may not be a problem.
Note also that since the exec command is what executes build systems, if show_panel_on_build is turned on in your user preferences (which it is by default unless you turn it off), the exec command will open a panel at the bottom of the window to tell you what the command you're running is doing.

Node-Webkit Child Process Exec

I want to execute a homebrew command for example
brew list
I followed the documentation and executed it like this:
child = exec('brew', function (error, stdout, stderr) {
console.log(stdout);
console.log(stderr);
});
I am getting a command not found error, and realized that if I do /usr/local/bin/brew as the command it works. However simply using 'brew' should work as well since I can run 'brew' from the command line just as such.
Why is this the case and what does it take to make 'brew' run as a child process in node? I have a feeling part of the issue because the command on node-webkit seems to execute from bin/sh.
Thanks
It may depend on how you're starting node-webkit and how you're setting your PATH. When I start from the command line, it inherits the environment variables from my command-line environment, including PATH. If I start by double clicking in a gui, it inherits from the system (presumably /etc/paths), and any additions I make in my .bashrc/.bash_profile have no effect.
Also, I'm no security expert, but my understanding of best practices would include using an absolute path to the executable you're running, so it's harder to spoof by setting an environment variable. By that measure, you're better off using the full path to brew anyway.

Installing a second instance of Bash (with different config)

I have repackaged a Bash RPM to include automatic logging to syslog. I am trying to work out a way to set this up so that it is used ONLY when a user or service account runs a command as root. The option I'm looking at is installing this version of Bash to an alternate location, and then pointing root to use that version as it's default shell.
Can someone go through the process of installing this RPM to an alternate path and associating the root account to it as the default shell? I have been having difficulty finding a way to do this when searching online.
Since you are repackaging the RPM, it is probably best to change the destination path directly in the RPM.
As for the default shell, run chsh -s /path/to/your/bash root to change it.
Be aware that this solution may not work for all purposes though. For example, running a script that starts with #!/bin/bash will still execute it with /bin/bash instead of your default login shell.

Resources