Passing in a parameter to Fabric - fabric

I'm having some issues passing in a parameter to Fabric. I'd like to provide a hostname that is then set on a specified host. Here is the basic structure of what I have tried, yet Fabric seems to interpret this as if to write "hostname %s" to the host instead of the actual value passed in.
#task
def configure_host(hostname):
sudo("hostname %s") % hostname
I'll note that this content is within a file called set_host in a fabfile directory. As such, I can run "fab -H user#1.2.3.4 set_host.configure_host" to run this code (it works when I hardcode the hostname). However, I have tried to run it as "fab -H user#1.2.3.4 set_host.configure_host:host=FunHostname" (noting my suffix), it fails.
The first issue is that it seems to be writing "hostname %s" instead of the actual hostname, but also not liking some of my sudo commands very much and some return a "Fatal error: sudo() received nonzero return code 1 while executing!". I can try and find a workaround for the latter but I'm wondering if my basic strategy for a user to pass in a parameter is logical. I thought this would be simple and I was following the outline under "Task arguments" here: http://docs.fabfile.org/en/latest/tutorial.html

You should include the string formatting inside the parentheses :
sudo("hostname %s" % hostname)
This way, Fabric will correctly replace %s with the value of the hostname variable.

Related

Mounting ecryptfs using C++ mount function

I am trying to mount ecryptfs from within a C++ program. I can definitely mount it without it asking questions by issuing this command at the prompt:
sudo mount -t ecryptfs -o "rw,key=passphrase:passphrase_passwd=geoff,ecryptfs_cipher=aes,ecryptfs_key_bytes=32,ecryptfs_passthrough=n,ecryptfs_enable_filename_crypto=n,no_sig_cache" ~/source/ ~/target/
Note that in reality, I am passing a full canonical path in case that matters.
But from within the program I get failure with errno=EINVAL after trying by using the mount() function with the same arguments:
mount("~/source/", "~/target/", "ecryptfs", MS_NODEV, "rw,key=passphrase:passphrase_passwd=geoff,ecryptfs_cipher=aes,ecryptfs_key_bytes=32,ecryptfs_passthrough=n,ecryptfs_enable_filename_crypto=n,no_sig_cache")
The program does launch with root privileges and I have checked that I have CAP_SYS_ADMIN.
The mount() function returns -1 and sets errno to EINVAL.
Have I got the arguments correct? Is this maybe a privileges issue?
EDIT: I got it to work by executing mount externally via system(), but would still like to use the function because of reasons.
I believe this is because mount -t ecryptfs is actually calling the helper executable mount.ecryptfs, and it's processing some of the options (in particular, key=) itself. What's actually passed to the kernel is different (you can see this by looking at /proc/mounts afterward).
If you look closely at https://manpages.ubuntu.com/manpages/kinetic/en/man7/ecryptfs.7.html, key= and ecryptfs_enable_filename_crypto= are listed under "MOUNT HELPER OPTIONS" - the actual kernel module's options are ecryptfs_sig=(fekek_sig) and ecryptfs_fnek_sig=(fnek_sig).
So, if you want to bypass the helper and do the mount directly, you'd need to load the tokens into the kernel's keyring with https://man7.org/linux/man-pages/man2/keyctl.2.html and replace key= with the resulting token signatures, like mount.ecryptfs did.
It does appear that there is a libecrytpfs with functions in ecryptfs.h like ecryptfs_add_passphrase_key_to_keyring which you can (presumably, not tested) use to do this in a way matching the mount.ecryptfs

Ssh command from Qt

I have a problem with ssh in my Qt application. I need to run a command which removes a file on a remote server. I tried to use a QProcess class to achieve it. So I pass "ssh" as a name of command and necessary args. In common it looks like this:
QStringList params;
params.append(" user#" + ::host +
" \"rm /tmp/" + ::fileName + "\"");
d->impDelProcess->start("ssh", params);
But after all it keeps asking a password, though I generated ssh keys and copied a public key to the remote server. Moreover, when I run the command above in the terminal like this:
ssh user#host "rm /path/fileName"
it works perfect. The file is deleted and no password is asked. So, the problem is somwhere in QProcess. Is any way to get rid of asking a password? Thank you!
Those are separate arguments, when you use string list. Try this:
params.append("user#" + ::host");
params.append("rm /tmp/" + ::fileName);
That will make Qt pass two arguments for ssh, the login string and the command to execute at remote host.
Important note! Above assumes ::filename does not contain spaces or anything else nasty!. You can get around spaces with this:
params.append("rm '/tmp/" + ::fileName + "'");
But it won't help against wild cards or .. in path... Imagine if file name was ../home/user/* for example... So that is better be trusted input, or you need to sanitize it (but that is beyond scope of this answer).
What you do in the question code is to construct a single argument, equivalent to this shell command line:
ssh 'user#host "rm /path/filename"'

Google Native Client Visual Studio Add-in: Webserver fails to start because arguments to httpd.py are invalid

I have an application that I turned into a simple Native Client App a year ago, and I've been trying to get it running again. However, when I try to run it, or any of the example VS projects, the web server fails to start, giving me usage hints for httpd.py, and saying "httpd.py: error: unrecognized arguments: 5103".
I wasn't able to find anything about this on the NaCL guide or on the net. I could probably troubleshoot the issue if I could see the script that starts the webserver, but I have no idea where this is stored.
The script that start the server is 'nacl_sdk\pepper_43\tools\httpd.py'. The problem is with the port argument being formated incorrectly.
The expected format is:
httpd.py [-h] [-C SERVE_DIR] [-p PORT] [--no-dir-check]
But, the received arguments formatted by the add-in is:
['--no_dir_check', '5103']
where the port prefix is missing and should be '-p 5103'
For a quick fix, add the following line
parser.add_argument('args', nargs=argparse.REMAINDER)
before the parse_args(args) in the main(args) method in httpd.py.
This will keep the unknown arguments from being parsed and will use the default value for port instead (5103).

vimrc to detect remote connection

At the moment I have to hard code the names of servers on my vimrc in order to either make it different on the remote machine. This is done by conditional statement using hostname() function in vim. I want to make the conditional to be based on the status of remote connection and not on the hostname. So...
The first possible solution I found was using the following bash command in system():
cat /proc/$PPID/status | head -1 | cut -f2
This does not work because I use GNU screen and this will not detect my connection status properly.
The second possible solution I am exploring right now is using who am i This reliably shows whether or not remote connection has been made from which client, but I have trouble getting it working with system()
if substitute(system('who am i'), "theclient", ????, "") == ""
...
How could I get ???? to extract my client name somehow??
Even if the second solution works, allowing me to use .vimrc for many different remote machines, it is still tied to one client. I want the conditional to work in all remote session, regardless of the client name. So I am wondering, is this possible?
The following line allows me to create a variable that detects the remote connection status:
let g:remoteSession = ($STY == "")
Now you can surround the lines that you want to be ignored in the remote connection via:
if g:remoteSession
...
endif
On a side note, I do not know how expensive it is look up the environment variable compared to the global variable, but I am guessing the difference is negligible. The system call in an environment like cygwin where fork() is inefficient, it is worth doing the optimization.
Instead of adding conditional logic to a shared ~/.vimrc, you could alternatively source system-local settings. I use the following:
" Source system-specific .vimrc first.
if filereadable(expand('~/local/.vimrc'))
source ~/local/.vimrc
endif
" Stop sourcing if inclusion guard exists.
if exists('g:loaded_vimrc')
finish
endif
" Common settings of .vimrc here...
I find this more scalable than trying to maintain an ever-changing list of hostnames in a central location.

popen and system behaves unexpectedly with multiple quoted file paths

I am trying to execute a dos command from within my C++ program, however soon as I add quotes to the output filepath (of a redirection) the command no longer gets executed and returns instantly. I've shown an example below of a path without spaces, but since paths may have spaces and thus be quoted for the shell to understand it properly I need to solve this dilemma - and I'm trying to get the simplest case working first.
i.e.
The following WORKS:
sprintf(exec_cmd,"\"C:/MySQL Server 5.5/bin/mysqldump.exe\" -u%s -p%s %s > C:/backup.bak",user,password,db_name);
system(exec_cmd);
The following does NOT work (notice the quotes around the output):
sprintf(exec_cmd,"\"C:/MySQL Server 5.5/bin/mysqldump.exe\" -u%s -p%s %s > \"C:/backup.bak\"",user,password,db_name);
system(exec_cmd);
I'm guessing it is choking somewhere. I've tried the same "exec_cmd" in popen to no avail.
Any help/advice is greatly appreciated.
I don't think your shell (cmd.exe) allows redirection to a file name with spaces. I couldn't make my command.com from DOS 6.22 accept it (I don't have a cmd.exe nearby to test).
Anyway, you can use the --result-file option to pass the redirection to the command itself.
mysqldump ... --result-file="file name" ...