Write a bash shell script that consumes a constant amount of RAM for a user defined time
Even if traditional Bash arrays are not supported, it may still be possible to create array-like variables using the eval
command built into the particular shell.
The following example script is based on some scripting I did when using BusyBox in an embedded Linux project. BusyBox uses the Almquist shell (also known as A Shell, ash, and sh), which does not support arrays.
#!/bin/ash
for index in 1 2 3 4 5; do
value=$(($index * 1024))
eval array$index=\"array[$index]: $value\"
done
for i in 1 3 5; do
eval echo \$array$i
done
Be careful with quoting when using eval
!
Output:
array[1]: 1024
array[3]: 3072
array[5]: 5120
Depending on your particular scenario, a script similar to the following may suffice.
#!/bin/ash
echo "Provide sleep time in the form of NUMBER[SUFFIX]"
echo " SUFFIX may be 's' for seconds (default), 'm' for minutes,"
echo " 'h' for hours, or 'd' for days."
read -p "> " delay
echo "begin allocating memory..."
for index in $(seq 1000); do
value=$(seq -w -s '' $index $(($index + 100000)))
eval array$index=$value
done
echo "...end allocating memory"
echo "sleeping for $delay"
sleep $delay
In my brief testing, this script consumed ~570M to ~575M physical memory* for the specified time period of 5 minutes.
* Monitored using top and memprof programs in separate tests
Rather high CPU usage with memory monitoring bash script
Any idea what's causing this and how I can optimize it?
The line
sleep 5
is inside the condition that checks whether the memory is within the specified range. Chances are that most of the times that memory isn't within this range, which causes the infinite loop without any sleep whatsoever and makes the script consume more resources than you'd expect it to.
Take the line outside the if
loop and that should help.
how to eat up all the android memory in an android application?
Since you are able to use ADB and have busybox you may be able to use a shell script that allocates memory until it's exhausted.
refer to Write a bash shell script that consumes a constant amount of RAM for a user defined time
ripped from that answer:
#!/bin/ash
echo "Provide sleep time in the form of NUMBER[SUFFIX]"
echo " SUFFIX may be 's' for seconds (default), 'm' for minutes,"
echo " 'h' for hours, or 'd' for days."
read -p "> " delay
echo "begin allocating memory..."
for index in $(seq 1000); do
value=$(seq -w -s '' $index $(($index + 100000)))
eval array$index=$value
done
echo "...end allocating memory"
echo "sleeping for $delay"
sleep $delay
How do I iterate over a range of numbers defined by variables in Bash?
for i in $(seq 1 $END); do echo $i; done
edit: I prefer seq
over the other methods because I can actually remember it ;)
Retrieve CPU usage and memory usage of a single process on Linux?
ps -p <pid> -o %cpu,%mem,cmd
(You can leave off "cmd" but that might be helpful in debugging).
Note that this gives average CPU usage of the process over the time it has been running.
Limit memory usage for a single Linux process
There's some problems with ulimit. Here's a useful read on the topic: Limiting time and memory consumption of a program in Linux, which lead to the timeout tool, which lets you cage a process (and its forks) by time or memory consumption.
The timeout tool requires Perl 5+ and the /proc
filesystem mounted. After that you copy the tool to e.g. /usr/local/bin
like so:
curl https://raw.githubusercontent.com/pshved/timeout/master/timeout | \
sudo tee /usr/local/bin/timeout && sudo chmod 755 /usr/local/bin/timeout
After that, you can 'cage' your process by memory consumption as in your question like so:
timeout -m 500 pdftoppm Sample.pdf
Alternatively you could use -t <seconds>
and -x <hertz>
to respectively limit the process by time or CPU constraints.
The way this tool works is by checking multiple times per second if the spawned process has not oversubscribed its set boundaries. This means there actually is a small window where a process could potentially be oversubscribing before timeout notices and kills the process.
A more correct approach would hence likely involve cgroups, but that is much more involved to set up, even if you'd use Docker or runC, which among things, offer a more user-friendly abstraction around cgroups.
Related Topics
How to Program Linux .Dts Device Tree Files
User-Data Scripts Is Not Running on My Custom Ami, But Working in Standard Amazon Linux
How to Set a Custom Baud Rate on Linux
What Is Path on a MAC (Unix) System
Why Exit Code 141 with Grep -Q
Where Does Eclipse Look for Eclipse.Ini Under Linux
Library Path When Dynamically Loaded
Linux Capabilities (Setcap) Seems to Disable Ld_Library_Path
"In-Source Builds Are Not Allowed" in Cmake
Does Gcc Have Any Options to Add Version Info in Elf Binary File
What Is the Purpose of the "-I" and "-T" Options for the "Docker Exec" Command
Why Linux/Gnu Linker Chose Address 0X400000
How to Establish Ssl Connection Upon Wget on Ubuntu 14.04 Lts